Я всегда знал, что хорошо быть щедрым с проверками ошибок в вашем коде и предоставлять сообщение об ошибке в случае выполнения определенных условий.Рассмотрим программу следующей структуры:
int main(const int argc, const char *argv[]) {
// read two integers M and N from input file 1 provided in argv[]
// read two integers K and L from input file 2 provided in argv[]
if (M*N < 1000000) {
allocate array A
} else {
printf("With your input values, the matrix will be too large!");
return 1;
}
if (K*L < 1000000) {
allocate array B
} else {
printf("With your input values, the matrix will be too large!");
return 1;
}
// multiply arrays elementwise
// free memory
return 0;
}
На данный момент не обращайте внимания на то, что этот код может быть реорганизован таким образом, что проверка правильности входных аргументов проверяется до того, как произойдет распределение (что было бы простым решением вэто простой пример).Моя актуальная проблема будет подробно рассмотрена ниже для тех, кто интересуется.
Если в псевдокоде выше A успешно выделен, но B не потому, что K * L превышает предел, операторы освобождения памяти в концепрограммы не достигаются, и утечка памяти связана с A. Каков наилучший способ избежать этой проблемы, если код не может быть реорганизован, как описано выше?Удаление return 1;
может вызвать другие ошибки в дальнейшем.Два других варианта, о которых я мог подумать, - это использование пресловутого оператора goto (я не осмелился) или включение всех бесплатных вызовов в условные выражения как;
if (K*L < 1000000) {
allocate array B
} else {
printf("With your input values, the matrix will be too large!");
free(A);
return 1;
}
, но это означало бы много кода.повторение, когда каждый имеет дело с большим количеством динамически распределенных массивов.Итак: какая структура программы рекомендуется для сочетания промежуточной проверки ошибок и обработки памяти?
Мой реальный случай: Я работаю с CUDA, который (для тех, кто с ней не знаком)) позволяет писать код, который будет выполняться на GPU.Весь (или большая часть) кода, связанного с этим API, возвращает флаг ошибки, который рекомендуется проверить перед продолжением программы.В моем случае, в какой-то момент в моей программе я выделяю память на GPU следующим образом (должен быть читаем для тех, кто знаком с C):
double *dev_I;
cudaError_t err;
err = cudaMalloc(&dev_I, N*M, sizeof(*dev_I)); // note: cudaMalloc takes a double pointer
if (err != cudaSuccess) { printf("Error allocating dev_I.\n"); return 1; }
Вот важная часть: следующий шаг -скопируйте память с хоста в место, где GPU может получить к нему доступ.Это выглядит примерно так:
err = cudaMemcpy(dev_I, host_I, M*N * sizeof(*host_I), cudaMemcpyHostToDevice);
if (err != cudaSuccess) { printf("Error copying dev_I"); return 1; }
И это та часть, которая меня беспокоит.Если выделение будет успешным, но копирование памяти не удастся, программа будет (должна) завершиться, и у меня останется утечка памяти.Отсюда мой вопрос, как с этим лучше всего справляться.