fscanf bus error: 10 when switching from Snow Leopard to Lion
First off, this snippet is not meant for production code. So please, no lec开发者_JAVA技巧turing about it "being unsafe." Thanks!
So, the following code is part of a parser that takes in a csv and uses it to populate an sqlite3 db. When compiled and ran in Snow Leopard, it worked just fine. Now that I've switched to Lion, the scanf statement throws Bus Error: 10. Specifically, it seems to have something to do with how I am consuming and discarding the '\n' at the end of each line:
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...
...
if I remove the last %*c, which is meant to consume the '\n' and ignore it so as to advance to the next line, the program does not crash. But of course does an incorrect parsing.
Also, mind you, the EOF doesn't seem to be the problem; I'e also tried a single fscanf statement instead of the while-loop shown above.
Any thoughts?
EDIT: Let me add that the code was originally compiled and ran in an intel core duo (32-bit) macbook with Snow Leopard and now I am compiling it and running it on a MacPro (64-bit) with Lion. So I wonder if it might have something to do with alignment?
Interesting. Bus errors are usually due to alignment issues but that may not be the case here since all you're scanning in is char
s.
One thing you may want to consider is to fgets
the entire line into a buffer and the sscanf
it. This will allow you to do two things:
- print out the line in a debug statement before
sscanf
ing it (or after scanning, if the expected conversion count is wrong), so you can see if there are any problems; and - not worry about trying to align the line-ending with
fscanf
, sincefgets
does a good job of this already.
So it would be something like (untested):
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);
}
}
You should also check the return values from the sqlite3_open
and fopen
calls, if this is anything more than "play" code (i.e., if there's the slightest possibility that those files may not exist).
I tried the following adaptation of your code on a Mac Mini running Lion (10.7.1) with 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;
}
I produced a 64-bit binary using:
gcc -O -std=c99 -Wall -Wextra xxx.c -o xxx
There were no warnings of any sort. Given the input data:
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
It produces the output:
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>>
The != EOF
vs == 5
change does not matter with the sample data, but is arguably more robust in general. The last line of data exploits your change in pattern and contains a comma in the 'last field'.
Since your code does not check that the file was opened correctly, I have to wonder whether that is your problem, though that's more likely to produce a segmentation violation than a bus error.
So, no answer to your problem - but some code for you to try.
精彩评论