【问题标题】:malloc and snprintf bus core dumpmalloc 和 snprintf 总线核心转储
【发布时间】:2013-04-09 15:15:27
【问题描述】:

以前有效的功能,突然拒绝合作。更准确地说是这个 sn-p:

    //If not, add to UIDS
    printf("line 78\n");
    free(s2);
    printf("line 82\n");
    char * ss = malloc(snprintf(NULL, 0, "%s:%d", myUIDs, userId) + 1);
    printf("line 84\n");
    sprintf(ss, "%s:%d", myUIDs, userId);
    free(myUIDs);
    myUIDs=ss;
    free(buffer);

程序在“第 82 行”之后的一行(不再是第 82 行,但它只是一个调试停止)与Segmentation Fault (core dumped) 一起失败。 如果我改变了

char * ss = malloc(snprintf(NULL, 0, "%s:%d", myUIDs, userId) + 1);

char * ss = malloc(snprintf(NULL, 0, "%s:%d", "", 1) + 1);

我得到的是Bus Error: Code dumped。我在这个程序上工作了很长时间,我有一种很明显的感觉,我经常因为疲惫而忽略,但目前没有程序员朋友寻求帮助。

上下文的整个函数:

char* myUIDs; //string containing all UID-s, separated by colon

void printProcessInformation(char pid[],int isSetP, int isSetN, int isSetU){
//find full path name to your "stat" file
//DIR *dir;
//struct dirent *ent;
//Creating string with /proc/PID
char * s = malloc(snprintf(NULL, 0, "%s%s", "/proc/", pid) + 1);
sprintf(s, "%s%s", "/proc/", pid);
//Creating string with /proc/PID/psinfo (full path)
char * fullPath = malloc(snprintf(NULL, 0, "%s%s", s, "/psinfo") + 1);
sprintf(fullPath, "%s%s", s, "/psinfo");
free(s);
//printf("%s\n",fullPath);

//Reading data from file
FILE* file = fopen(fullPath, "r");
printf("line 37\n");
char* buffer;
buffer = (char*) malloc(sizeof(psinfo_t));
printf("line 40\n");
if(file == NULL)
{
    //perror("Error: Couldn't open file");
    return;
}
fread((void *)buffer, sizeof(psinfo_t), 1, file);
psinfo_t* pData = (psinfo_t*) buffer;
time_t sTime=pData->pr_start.tv_sec; 
int pr_pid=pData->pr_pid;
char* fname=pData->pr_fname;
free(buffer);
buffer = (char*) malloc(sizeof(stat));
stat(fullPath,buffer);
struct stat* fileStat=(struct stat*) buffer;
fclose(file);
int userId=fileStat->st_uid;
struct passwd* pw=getpwuid(userId);
char* uid=pw->pw_name;
printf("line 58\n");
if(isSetU<0){
    //Print results
    printf("%8s", uid);
    if(isSetP>0)
    printf(" %5d",pr_pid);
    printf(" %16s %.24s\n", fname, ctime(&sTime));
    free(buffer);
}else{
    //Or else, add UID to UIDS if it didn't appear before
    //check if UID is in UIDS
    printf("line 70\n");
    char * s2 = malloc(snprintf(NULL, 0, "%s:%d", "", userId) + 1);
    printf("line 72\n");
    snprintf(s2, "%s:%d", "", userId);
    if(strstr(myUIDs,s2)!=NULL){
        free(s2);
        free(buffer);
        return;
    }
    //If not, add to UIDS
    printf("line 78\n");
    free(s2);
    printf("line 82\n");
    char * ss = malloc(snprintf(NULL, 0, "%s:%d", "", 1) + 1);
    printf("line 84\n");
    sprintf(ss, "%s:%d", myUIDs, userId);
    free(myUIDs);
    myUIDs=ss;
    free(buffer);
}
}

【问题讨论】:

  • 也许你应该在使用具有负返回值的 malloc 之前检查 snprintf()...
  • @Mppl 不幸的是,这不是问题。

标签: c++ c unix malloc solaris


【解决方案1】:

我在进一步审查时发现了几个问题...

简而言之,您遇到的错误似乎不是您正在执行的行的结果,而是先前内存损坏的副作用。

  1. 你在哪里初始化myUIDs?如果尚未根据提供的代码定义它,您似乎可以访问它

  2. 1234563到释放的内存。然而,您稍后会尝试在代码中读取它......这很可能会引导您随机浏览内存。
  3. 在代码中有多个实例,您正在动态分配内存,然后尝试使用它而不验证您是否确实获得了请求的分配。

  4. 您正在根据来自 snprintf() 的返回值调用 malloc(),但从未验证 snprintf() 是否返回了非负值。虽然,我怀疑这是一个问题,但这是不明智的。

可以肯定的是,您所描述的症状是堆损坏的结果。问题是在哪里。我强烈推荐使用 valgrind。

此外,如果可用,请查看 asprintf() 而不是您正在做的 malloc( snprintf() ) 工作。

【讨论】:

  • 以前可以,即使在这个程序中,也可以看到上面几行非常相似的代码stackoverflow.com/questions/1383649/…
  • snprintf() 可以根据 C99 和 SUSv2 使用 NULL 缓冲区和零大小调用。在前者中,它返回将要写入的字符数。在后者中,一个小于 1 的值。
  • 再次编辑以对我在提供的代码中看到的错误提供更简洁的分析......尤其是考虑到对原始问题的编辑。
  • 不幸的是,这似乎不是问题(编辑:我在您的分析之前添加了此评论,现在阅读)。 EDIT2:您的 cmets 似乎很明智。我会在我睡觉后应用它们。感谢您深入分析我的代码。
猜你喜欢
  • 2021-12-06
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 2020-12-08
  • 2020-01-31
  • 2015-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多