Ошибка шины fscanf: 10 при переключении со Snow Leopard на Lion - PullRequest
3 голосов
/ 08 октября 2011

Во-первых, этот фрагмент не предназначен для производственного кода. Поэтому, пожалуйста, не читайте лекций о том, что это «небезопасно». Спасибо!

Итак, следующий код является частью синтаксического анализатора, который принимает CSV и использует его для заполнения базы данных sqlite3. Когда он скомпилирован и запущен в Snow Leopard, он работал просто отлично. Теперь, когда я переключился на Lion, оператор scanf выдает ошибку шины: 10. В частности, похоже, что это связано с тем, как я потребляю и отбрасываю '\ n' в конце каждой строки:

int main()
{
  sqlite3* db;
  sqlite3_open("someExistingDB.sqlite3", &db);

  FILE *pFile;
  pFile = fopen("excelData.csv","r");

  char name[256],country[256], last[256], first[256], photoURI[256];
  char sqlStatement[16384];

  while(fscanf(pFile, "%[^,],%[^,],%[^,],%[^,],%[^\n]%*c", name, country, last,first, photoURI) != EOF)
  {
          blah...

   ...

если я удаляю последний% * c, который должен использовать '\ n', и игнорировать его, чтобы перейти к следующей строке, программа не завершится сбоем. Но, конечно, делает неправильный анализ.

Кроме того, учтите, что EOF, похоже, не является проблемой; Я также попробовал один оператор fscanf вместо цикла while, показанного выше.

Есть мысли?

РЕДАКТИРОВАТЬ: Позвольте мне добавить, что код был изначально скомпилирован и запущен в MacBook Intel Core Duo (32-разрядный) с Snow Leopard, и теперь я собираю его и запускаю на MacPro (64-разрядный) с Lion. Поэтому мне интересно, может ли это быть как-то связано с выравниванием?

Ответы [ 2 ]

1 голос
/ 08 октября 2011

Я попробовал следующую адаптацию вашего кода на Mac Mini под управлением Lion (10.7.1) с XCode 4.

#include <stdio.h>

static void print(const char *tag, const char *str)
{
    printf("%8s: <<%s>>\n", tag, str);
}

int main(void)
{
    FILE *pFile = fopen("excelData.csv","r");
    char name[256], country[256], last[256], first[256], photoURI[256];

    while (fscanf(pFile, "%[^,],%[^,],%[^,],%[^,],%[^\n]%*c",
                        name, country, last, first, photoURI) == 5)
    {
        print("name",     name);
        print("country",  country);
        print("last",     last);
        print("first",    first);
        print("photoURI", photoURI);
    }
    return 0;
}

Я создал 64-битный двоичный файл, используя:

gcc -O -std=c99 -Wall -Wextra xxx.c -o xxx

Не было никаких предупреждений. С учетом входных данных:

Monster,United States,Smith,John,http://www.example.com/photo1
Emancipated Majority,Canada,Jones,Alan,http://www.example.com/photo2
A Much Longer Name Than Any Before,A Land from Far Away and In the Imagination Most Beautiful,OneOfTheLongerFamilyNamesYou'llEverSee,ALongishGivenName,http://www.example.com/photo3/elephant/pygmalion/photo3,x31

Производит вывод:

    name: <<Monster>>
 country: <<United States>>
    last: <<Smith>>
   first: <<John>>
photoURI: <<http://www.example.com/photo1>>
    name: <<Emancipated Majority>>
 country: <<Canada>>
    last: <<Jones>>
   first: <<Alan>>
photoURI: <<http://www.example.com/photo2>>
    name: <<A Much Longer Name Than Any Before>>
 country: <<A Land from Far Away and In the Imagination Most Beautiful>>
    last: <<OneOfTheLongerFamilyNamesYou'llEverSee>>
   first: <<ALongishGivenName>>
photoURI: <<http://www.example.com/photo3/elephant/pygmalion/photo3,x31>>

Изменение != EOF против == 5 не имеет значения для данных выборки, но, возможно, в целом более устойчиво. Последняя строка данных использует ваше изменение шаблона и содержит запятую в «последнем поле».

Поскольку ваш код не проверяет, правильно ли был открыт файл, я должен задаться вопросом, является ли это вашей проблемой, хотя это скорее приведет к нарушению сегментации, чем к ошибке шины.

Итак, нет ответа на вашу проблему - но какой-то код для вас.

1 голос
/ 08 октября 2011

Интересно. Ошибки шины обычно возникают из-за проблем с выравниванием, но в данном случае это не так, поскольку все, что вы сканируете, это char s.

Одна вещь, которую вы можете пожелать рассмотреть, это fgets вся строка в буфер и sscanf это. Это позволит вам сделать две вещи:

  • распечатывает строку в операторе отладки до sscanf ее (или после сканирования, если ожидаемое количество конверсий неверно), чтобы вы могли увидеть, есть ли какие-либо проблемы; и
  • не беспокойтесь о попытке выровнять конец строки с fscanf, поскольку fgets уже хорошо справляется с этой задачей.

Так что это было бы что-то вроде (не проверено):

char bigHonkinBuffer[16384];
while (fgets (bigHonkinBuffer, sizeof(bigHonkinBuffer), pFile) != NULL) {
    if (sscanf(bigHonkinBuffer, "%[^,],%[^,],%[^,],%[^,],%[^\n]", name, country, last,first, photoURI) != 5) {
        // printf ("Not scanned properly: [%s]\n", bigHonkinBuffer);
        exit (1);
    }
}

Вам также следует проверить возвращаемые значения из вызовов sqlite3_open и fopen, если это нечто большее, чем код "воспроизведения" (т. Е. Если есть малейшая вероятность того, что эти файлы могут не существовать).

...