ошибка шины fscanf: 10 при переключении со Snow Leopard на Lion

#c #macos #memory-management #osx-lion #scanf

#c #macos #управление памятью #osx-lion #scanf

Вопрос:

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

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

 int main()
{
  sqlite3* db;
  sqlite3_open("someExistingDB.sqlite3", amp;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, показанного выше.

Есть мысли?

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

Комментарии:

1. Это может пойти не так в нескольких местах; Я предлагаю проверить fopen(3) и sqlite3_open() для успеха распечатать фактическое возвращаемое значение из fscanf(3) (возможно, оно вернуло a 0 для ранней ошибки сопоставления?). Кроме того, возможно, попробуйте заменить %*c на ` ` (один пробел), поскольку любой пробел во входной спецификации потребляет все пробелы до следующего символа, не содержащего пробелов.

2. Обратите внимание, что fscanf здесь может вернуться где-то между -1 и 5, в зависимости от того, сколько элементов было успешно прочитано. Если он читает между 0 и 4, в ваших строках останется ненужный мусор, что может привести к ошибке шины.

Ответ №1:

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

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

  • распечатайте строку в инструкции debug перед 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 вызовов and , если это что-то большее, чем код «воспроизведения» (т. Е. Если есть малейшая вероятность того, что эти файлы могут не существовать).

Ответ №2:

Я попробовал следующую адаптацию вашего кода на 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 vs == 5 не имеет значения для выборочных данных, но в целом, возможно, более надежно. Последняя строка данных использует ваше изменение шаблона и содержит запятую в «последнем поле».

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

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