2013-04-09 28 views
-1

以前工作過的功能,突然拒絕合作。更確切地說這個片段:malloc和snprintf總線核心轉儲

//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); 
} 
} 
+0

也許你應該檢查snprintf()的負值返回值,然後再使用帶有該值的malloc ... – Mppl 2013-04-09 15:19:49

+0

@Mppl不幸的是,那不是問題所在。 – Xyzk 2013-04-09 15:30:56

回答

3

有幾個問題我在進一步審查看到...

簡單地說,你所得到的錯誤不會顯得的結果你正在執行的行,而是一個以前腐敗的內存的副作用。

  1. 你在哪裏初始化myUIDs?它看起來像當它尚未根據所提供的代碼中定義的,你可以訪問它

  2. 您分配從pDatafname這是一個指向動態分配buffer ...你以後免費放在下一行的執行,這意味着fname現在指向釋放內存。然而,你試圖在後面的代碼中讀取它......這可能會導致你隨機散步通過內存。

  3. 代碼中有多個實例可以動態分配內存,然後嘗試使用它,而無需驗證是否確實獲得了您請求的分配。

  4. 您是基於從snprintf()返回值而沒有驗證該snprintf()返回你一個非負值調用malloc()。雖然,我懷疑這是一個問題,這是不明智的。

可以肯定,您所描述的症狀是堆損壞的結果。問題在哪裏。我會強烈建議使用valgrind。

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

+0

它的工作之前,即使在這個程序中,你可以看到幾行上面非常類似的代碼http://stackoverflow.com/questions/1383649/concatenating-strings-in-c-which-method-is-more-efficient – Xyzk 2013-04-09 15:25:25

+0

可以根據C99和SUSv2使用'NULL'緩衝區和零大小來調用snprintf()。在前者中,它返回將要寫入的字符數。在後者中,值小於1。 – Hasturkun 2013-04-09 15:26:24

+0

@ XyzK&Hasturkun - 查看修改 – 2013-04-09 15:34:05