fscanf总线错误:从Snow Leopard切换到Lion时为10

时间:2011-10-08 00:03:22

标签: c macos memory-management osx-lion scanf

首先,此代码段不适用于生产代码。所以,请不要讲它“不安全”。谢谢!

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

有什么想法吗?

编辑:让我补充一点,代码最初编译并运行在带有Snow Leopard的intel core duo(32位)macbook中,现在我正在编译它并在Lion上运行MacPro(64位)。所以我想知道它是否与对齐有关?

2 个答案:

答案 0 :(得分:1)

有趣。总线错误通常是由于对齐问题造成的,但这可能并非如此,因为您扫描的所有内容都是char

这将允许您做两件事:

  • fgets之前打印出调试语句中的行(或者在扫描之后,如果预期的转换计数错误),那么你可以看看是否有任何问题;和
  • 不用担心尝试将行结尾与sscanf对齐,因为sscanf已经很好地完成了此工作。

所以它会像(未经测试的):

fscanf

您还应该检查fgetschar 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); } } 来电的返回值,如果这超过“播放”代码(即,如果这些文件可能不存在,则最轻微)

答案 1 :(得分:1)

我在使用XCode 4运行Lion(10.7.1)的Mac Mini上尝试了以下代码修改。

#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更改与示例数据无关,但一般来说可能更强大。最后一行数据利用您对模式的更改,并在“最后一个字段”中包含一个逗号。

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

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