fopen не может открыть доступный для записи файл при использовании nvcc

РЕДАКТИРОВАТЬ: я считаю, что проблема связана с тем, что nvcc вызывает компилятор C++ вместо компилятора C из-за ошибки, которую я получаю, когда не передаю вызов malloc(3) в char*. Меня привело к этому утверждению: Неверное преобразование из void* в char**

РЕДАКТИРОВАТЬ: он отлично работает, если я использую fileO = fopen(version, "w"); в обход вызовов strcpy и strcat. (ха-ха, я сказал освистывание...)

Итак, у меня есть программа CUDA, в которой я собрал файловый ввод-вывод из последовательной версии той же программы (не CUDA). Точно такой же код работает с обычными компиляциями gcc, но не через nvcc. Я знаю, что nvcc отключает C/C++ от собственного компилятора C++, но по какой-то причине он просто не открывает доступный для записи файл. Я открывал и закрывал другой файловый поток для чтения данных в приведенном выше коде, но я делаю это в своей последовательной версии, и там все работает нормально.

Вот соответствующий код:

else 
{
    char* version = "matrixExpCUDAx";
    char* filename = (char *)malloc(strlen(version) + strlen(argv[3]));

    strcpy(filename, version);
    strcat(filename, argv[3]);

    FILE *fileO;
    fileO = fopen(filename, "w");   

    if(DEBUG)
    {
        for (i=0; i<(dim*dim); i++) fprintf(stderr, "%f\n", h_O[i]);
    }
    else
    {
        if(fileO != NULL)
        {
            for (i=0; i<(dim*dim); i++)
            {
                fprintf(fileO, "%f\n", h_O[i]);
            }
            fclose(fileO);
        }
        else fprintf(stderr, "Write file failed to create\n");
    }
}
....

Каждый раз получаю сообщение "Ошибка создания файла для записи".

Есть идеи?


person Heath Carroll    schedule 21.03.2012    source источник
comment
Обратите внимание на неудачное форматирование кода вверху; ты можешь это исправить? (другие тоже могут это исправить, но если несколько человек попытаются отредактировать пост одновременно, кого-то это будет раздражать..)   -  person sarnold    schedule 21.03.2012
comment
Также обратите внимание, что nvcc не является компилятором, и он не скомпилировал этот код, а ваш стандартный хост-компилятор C++ (gcc, судя по тегам). Несмотря на внешний вид, этот вопрос не имеет ничего общего с CUDA или цепочкой инструментов CUDA, а связан с непониманием завершения строки в C.   -  person talonmies    schedule 21.03.2012
comment
@talonmies: Спасибо, да. Я отметил, что nvcc использует системный компилятор C в исходном посте. Я не думаю, что это завершение строки, так как он работает без конкретных частей кода CUDA и gcc в качестве компилятора. Я все же посмотрю, на всякий случай.   -  person Heath Carroll    schedule 21.03.2012


Ответы (1)


char* filename = (char *)malloc(strlen(version) + strlen(argv[3]));

Во-первых, вам не нужно приводить возвращаемое значение из malloc(3). Если вы добавите #include <stdlib.h> в свою программу, вы получите прототип malloc(3), который сообщает компилятору, как правильно обрабатывать возвращаемое значение из malloc(3). Самостоятельное приведение может скрыть полезные предупреждения или ошибки, которые могут выявить ошибки. Добавьте #include и удалите слепок.

Кроме того, кажется, что для вашего имени файла не выделяется достаточно памяти; не забывайте, что strlen(3) не включает пробел для завершающего байта ASCII NUL в конце строки, но вашему filename определенно понадобится завершающий NUL.

Всякий раз, когда вы видите такой код:

bar = malloc(strlen(foo));

это почти всегда ошибка. Вместо этого он должен выглядеть так:

bar = malloc(strlen(foo)+1);

Даже если вычисление размера выполняется в другом месте, мне часто нравится помещать +1 в вызов malloc() специально, просто чтобы убедиться, что я знаю, что он будет там в будущем.

Если ваш file0 равен NULL, вам, вероятно, также следует позвонить perror(3), чтобы сообщить вам, почему вы не смогли открыть файл. Это может быть «отказано в доступе». Возможно, текущий рабочий каталог больше не существует. (Это не позволит вам создавать файлы в каталоге, даже если в противном случае разрешения вашей файловой системы позволяют вам создавать файлы.)

person sarnold    schedule 21.03.2012
comment
Сарнольд спасибо за ответ. Я включаю stdlib.h вверху, но при компиляции получаю сообщение об ошибке: значение типа void нельзя использовать для инициализации сущности типа char *. Я знаю, что gcc автоматически связывает stdlib, но возможно ли, что мне нужно будет сообщить об этом nvcc? Это не кажется мне правильным, исходя из моего понимания того, как nvcc вызывает gcc... Что касается проблемы с длиной, я почти уверен, что получаю нулевой термин, так как я начинаю с char версия переменной, прежде чем я обработаю ее в имя файла. Я думаю, что strlen(version) часть malloc получает это. Я пробовал +1, но без изменений. - person Heath Carroll; 21.03.2012
comment
О, и perror() возвращает No такого файла или каталога, когда я компилирую при преобразовании malloc() в char*. - person Heath Carroll; 21.03.2012
comment
Ваше самое верхнее редактирование объясняет кастинг malloc(3). Мне придется смириться с тем, что я никогда не пойму C++ — он слишком отличается для меня. Я не уверен, почему вы до сих пор не получаете такого файла или каталога - можете ли вы напечатать имя файла и убедиться, что оно по-прежнему имеет смысл? - person sarnold; 22.03.2012