I'd probably write it like this, adding debugging output to determine the cause. If you get an error, I'd comment out all but the first Salesforce object functions and see what you get in the output.
%%[
set @ContactID = QueryParameter('c')
set @contactRows = RetrieveSalesforceObjects(
"Contact"
,"AccountId,Email"
,"id", "=", @ContactID
)
set @contactRowCount = rowcount(@contactRows)
output(concat("<br>contactRowcount: ", @contactRowCount))
if @contactRowCount > 0 then
set @contactRow = Row(@contactRows, 1)
set @AccountId = Field(@contactRow, "AccountId")
set @email = Field(@contactRow, "Email")
output(concat("<br>AccountId: ", @AccountId))
output(concat("<br>email: ", @email))
set @falseVal = false
set @updateContact = UpdateSingleSalesforceObject(
"Contact", @ContactID
, "Optin_A__c", @falseVal
, "Optin_B__c", @falseVal
)
set @updateAccount = UpdateSingleSalesforceObject(
"Account", @AccountId
, "ID_Company__c", ""
)
output(concat("<br>updateContact: ", @updateContact))
output(concat("<br>updateAccount: ", @updateAccount))
endif
]%%
Also, it's not the best practice to pass around the subscriber key in the URL. The CloudPagesURL() function allows you to pass encrypted parameters that you can retrieve from the URL using the AttributeValue() function. I'd use that instead of QueryParameter().
Reference