2011-10-08 55 views
3

首先,此代码段不适用于生产代码。所以,请不要说“不安全”。谢谢!fscanf总线错误:从Snow Leopard切换到Lion时为10

因此,下面的代码是一个解析器的一部分,它接收一个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循环。

有什么想法?

编辑:让我补充说,该代码最初编译和运行在雪豹与英特尔核心二重奏(32位)的MacBook,现在我正在编译它并在MacPro(64位)上运行它与狮子。所以我想知道它是否可能与对齐有关?

+0

这可能会在几个地方出错;我建议检查'fopen(3)'和'sqlite3_open()'是否成功,从'fscanf(3)'打印实际返回值(也许它返回一个'0'来表示早期匹配失败?)。另外,也许尝试用''(单个空格)替换'%* c',因为输入规范中的任何空白都会消耗所有空白,直到下一个非空白字符。 – sarnold

+0

请注意,'fscanf'可以返回-1和5之间的任何位置,具体取决于成功读取了多少项。如果它读取0和4之间的数字,则会在字符串中留下垃圾,这可能会导致总线错误。 –

回答

1

有趣。总线错误通常是由于对齐问题导致的,但这可能不是这种情况,因为您扫描的所有内容都是char s。

有一点你可能想要考虑的是把整个线路改成fgetssscanf吧。这将允许你做两件事情:

  • 打印出调试语句行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_openfopen调用检查返回值,如果这是什么比“玩”的代码更(即,如果这些文件有可能不存在)。

+0

我会试试看。谢谢。 – SaldaVonSchwartz

1

我想你的代码的以下适应上的Mac Mini与的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位二进制使用运行狮(10.7.1):

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变化不会与样本数据重要,但可以说是更稳健的总称。最后一行数据利用您的模式变化,并在'最后一个字段'中包含逗号。

由于您的代码没有检查文件是否正确打开,所以我不得不怀疑这是否是您的问题,尽管这可能会产生分割冲突而不是总线错误。

所以,没有回答你的问题 - 但有些代码让你试试。