When I ran the APUE sample code shown below on my Mac, it throws a EXC_BAD_ACCESS exception. I have checked the file cursor, and it is in the right position 12. I even try to replace the fprintf
with fputc
. After that, it works fine and the exception is gone. But I want to know what happened out there and why.
#include "apue.h"
#define BSZ 48
int main(){
FILE *fp;
char buf[BSZ];
memset(buf,'a',BSZ-2);
buf[BSZ-2]='\0';
buf[BSZ-1]='X';
if ((fp = fmemopen(buf,BSZ,"w+")) == NULL)
err_sys("fmemopen failed");
printf("initial buffer contents: %s\n",buf);
fprintf(fp, "hello, world");
printf("before flush: %s\n", buf);
fflush(fp);
printf("after fflush: %s\n",buf);
printf("len of string in buf = %ld\n",(long)strlen(buf));
memset(buf,'b', BSZ-2);
buf[BSZ-2]='\0';
buf[BSZ-1]='X';
fprintf(buf, "hello, world");
// fputc('a',fp);
fseek(fp,0,SEEK_SET);
printf("after fseek: %s\n",buf);
printf("len of string in buf = %ld\n", (long)strlen(buf));
}
Console out put as below:
/Users/heping/Documents/APUE-Example-Code/stdio/cmake-build-debug/memstr
initial buffer contents:
before flush: hello, world
after fflush: hello, world
len of string in buf = 12
Exception: EXC_BAD_ACCESS (code=1, address=0x8)
Process finished with exit code 9
Last stack frame like this: it seems like that something is wrong with the file lock, I think.
As already discussed in the comments, you passed the buffer buf
to fprintf()
and not the FILE
pointer fp
, which causes UB.
Every reasonable compiler will print a warning when you trying to do something like that you enabled the warning flags. You can avoid a lot of debugging when you enable all compiler warnings and only disable specific warnings when you are sure you do not want a warning for some type of error.
As mentioned here How to enable all compiler warnings in CLion?, you can enable warnings by adding the compiler flags to CMakeLists.txt
. For all warnings for C code, adding this line:
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -Werror")
-Wall
will enable all normal warnings, -Wextra
will enable additional warnings, -Wpedantic
will warn about not strictly following the C standard you specified and -Werror
will turn every warning into a error, so you have to fix the error before you can compile the program. In case you get warnings you do not want, you can disable them the same way, like this:
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -Werror -Wno-cast-function-type")
-Wno-cast-function-type
will disable warnings about casting function pointers to different function pointers. You can read about all the warning options here