#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)
(возможно, оно вернуло a0
для ранней ошибки сопоставления?). Кроме того, возможно, попробуйте заменить%*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
не имеет значения для выборочных данных, но в целом, возможно, более надежно. Последняя строка данных использует ваше изменение шаблона и содержит запятую в «последнем поле».
Поскольку ваш код не проверяет правильность открытия файла, я должен задаться вопросом, является ли это вашей проблемой, хотя это, скорее всего, приведет к нарушению сегментации, чем к ошибке шины.
Итак, ответа на вашу проблему нет, но есть некоторый код, который вы можете попробовать.