【问题标题】:SIGABRT on fopen callSIGABRT 在 fopen 呼叫
【发布时间】:2013-10-04 08:08:46
【问题描述】:

我正在编写一个 sn-p 代码来检查文件是否存在。当用户传入一个仅带有名称(无斜杠)的文件参数时,我将使用 PATH 环境变量中的路径检查该文件是否存在。我在 Ubuntu 上用 gcc 编译并且一直在使用 gdb。我找到了导致 SIGABRT 的线路,但不确定信息告诉我什么。这是我第一次使用 gdb。这是我的 sn-p:

char* PATH = NULL;
PATH = (char*)getenv( "PATH" );
char* pathtoken = strtok( PATH, ":" );
int index = 0;

while ( pathtoken != NULL )
{
    index++;
    printf( "%s\n", pathtoken );
    char* pathdir = (char*)malloc( sizeof(pathtoken) );
    strcpy( pathdir, pathtoken );
    GetFullPath( pathdir, filename );
    inputstream = fopen( pathdir, "r" );

    if ( inputstream != NULL)
    {
        free( pathdir );
        break;
        }

        free( pathdir );
        pathtoken = strtok( NULL, ":" );
    }

char* GetFullPath( char* dirpath, char* filename )
{
    //Append back slash
    int len = strlen(dirpath);
    dirpath[len] = '/';
    dirpath[len+1] = '\0';

    return strcat( dirpath, filename );
}

它发生在 fopen 行的第一次迭代中。这是我的 gdb 输出

启动程序:/home/seapoe/Documents/OsClass/CodePractice/a.out text1 /usr/lib/lightdm/lightdm

断点 1,主要 (argc=2, argv=0xbffff3a4) 在 xssh.c:87

87 GetFullPath(路径目录,文件名);

(gdb) 下一个

89 输入流 = fopen(pathdir, "r");

(gdb) 打印路径目录

$5 = 0x804c008 "/usr/lib/lightdm/lightdm/text1"

(gdb) 打印路径目录[strlen(pathdir)]

$6 = 0 '\000'

(gdb) 打印路径目录[strlen(pathdir)+1]

$7 = 0 '\000'

(gdb) 打印路径目录[strlen(pathdir)+2]

$8 = 0 '\000'

(gdb) 打印路径目录[strlen(pathdir)-1]

$9 = 49 '1'

(gdb) 下一个

* 检测到 glibc /home/seapoe/Documents/OsClass/CodePractice/a.out: free(): invalid 下一个尺寸(正常):0x0804c018 **

======= 回溯:=========

/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb7e97ee2]

/lib/i386-linux-gnu/libc.so.6(+0x65db5)[0xb7e87db5]

/lib/i386-linux-gnu/libc.so.6(fopen+0x2b)[0xb7e87deb]

/home/seapoe/Documents/OsClass/CodePractice/a.out[0x8048a77]

/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7e3b4d3]

/home/seapoe/Documents/OsClass/CodePractice/a.out[0x8048771]

======= 内存映射:========

08048000-0804a000 r-xp 00000000 08:01 536263 /home/seapoe/Documents/OsClass /CodePractice/a.out

0804a000-0804b000 r--p 00001000 08:01 536263 /home/seapoe/Documents/OsClass/CodePractice/a.out

0804b000-0804c000 rw-p 00002000 08:01 536263 /home/seapoe/Documents/OsClass/CodePractice/a.out

0804c000-0806d000 rw-p 00000000 00:00 0 [堆]

b7df3000-b7e0f000 r-xp 00000000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e0f000-b7e10000 r--p 0001b000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e10000-b7e11000 rw-p 0001c000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e21000-b7e22000 rw-p 00000000 00:00 0

b7e22000-b7fc5000 r-xp 00000000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc5000-b7fc7000 r--p 001a3000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc7000-b7fc8000 rw-p 001a5000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc8000-b7fcb000 rw-p 00000000 00:00 0

b7fd9000-b7fdd000 rw-p 00000000 00:00 0

b7fdd000-b7fde000 r-xp 00000000 00:00 0 [vdso]

b7fde000-b7ffe000 r-xp 00000000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

b7ffe000-b7fff000 r--p 0001f000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

b7fff000-b8000000 rw-p 00020000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

bffdf000-c0000000 rw-p 00000000 00:00 0 [堆栈]

程序收到信号 SIGABRT,已中止。

__kernel_vsyscall()中的0xb7fdd424

调用 GetFullPath 后,您可以看到在 fopen 调用之前返回了一个有效路径

【问题讨论】:

    标签: c linux gcc file-io gdb


    【解决方案1】:
    char* pathdir = (char*)malloc( sizeof(pathtoken) );
    

    错了。 sizeof(pathtoken) 将为您提供系统上指针的大小(4 或 8)。 你想要

    pathdir = strdup(pathtoken)
    

    这也是错误的,因为您正在尝试追加它。只需将 pathdir 设为 MAX_PATH(或 PATH_MAX 取决于您的操作系统)长度的字符数组即可。

    【讨论】:

      【解决方案2】:

      问题是这样的:

      sizeof(pathtoken)
      

      sizeof 操作符不是这样工作的,它只是给你一个指针变量的大小,并没有提供足够的空间。你真正想要的是:

      char* pathdir = malloc( strlen(pathtoken) + 1 );
      

      或者,作为 MK。声明,如果您在GetFullPath() 期间不尝试在其中填充更多字符,这就是您想要的。作为补偿,要么按照他的建议设置一个足够大的静态数组,要么执行以下操作:

      pathdir = GetFullPath( pathdir, filename );
      
      ....
      
      char* GetFullPath( char* dirpath, char* filename )
      {
          char * temp_path = malloc(strlen(dirpath) + strlen(filename) + 2);
          if ( temp_path == NULL ) {
              fprintf(stderr, "No memory!\n");
              exit(EXIT_FAILURE);
          }
      
          sprintf(temp_path, "%s/%s", dirpath, filename);
          free(dirpath);
          return temp_path;
      }
      

      不要在 C 中从malloc() 转换返回值。

      【讨论】:

      • 绝对喜欢这个更好
      猜你喜欢
      • 1970-01-01
      • 2012-06-30
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多