2013-04-21 54 views
0

我找不出爲什麼我的代碼無法正常工作。我試圖創建類似於P2P文件傳輸的東西,其中多個線程同時從預先存在的服務器程序抓取文件的不同部分。然而,我現在遇到的實際問題要簡單得多。爲什麼我的printf打印錯誤的值?

由於您無法將多個參數傳遞到pthread_create中,因此我創建了一個具有我想傳遞的兩條信息的結構。我還創建指向這些結構的數組,並通過它在指針之前單獨初始化每個之一。

printf("In thread: port=%d & ipAddr=%s\n",conn->port,conn->ipAddr); 

當該線路運行,一切正常打印出與正確的端口號和IP地址。

printf("Size of chunk %d received by %lu on port %d: %d bytes\n",chunkNum,pthread_self(),conn->port,sizeRec); 

但是,當該行不久後運行時,端口號不能正確打印。而不是9210和9211,我得到0和134520848.否則,一切似乎都在工作,所以我認爲它可能只是某種printf問題,但在繼續執行下一部分之前,我想確定一下我的項目。

如果任何人有任何想法,爲什麼相同的變量會打印一個值,並在完成不同的幾行後沒有更改時,這將對我很有幫助。我已經在下面列出了所有的代碼以供參考。謝謝你的幫助!

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <pthread.h> 

char * file_name = "output.txt"; 
int nextChunk = 0; 

pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER; 

struct connection{ 
    int port; 
    char* ipAddr; 
}; 

void* getFile(void* args) { 
    int con_fd = 0; 
    int ret = 0; 
    struct sockaddr_in serv_addr; 
    struct connection* conn = (struct connection*)args; 
    printf("In thread: port=%d & ipAddr=%s\n",conn->port,conn->ipAddr); 

memset(&serv_addr, 0, sizeof(struct sockaddr)); 
serv_addr.sin_family = AF_INET; 
//printf("port number: %d\n",conn->port); 
serv_addr.sin_port = htons(conn->port); 
serv_addr.sin_addr.s_addr = inet_addr(conn->ipAddr); 
int sizeRec; 
char buf[1024]; 
while(1) { 
    con_fd = socket(PF_INET, SOCK_STREAM, 0); 
    if (con_fd == -1) { 
     printf("Socket Error\n"); 
     fflush(stdout); 
     return 0; 
    } 
    ret = connect(con_fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)); 
    if (ret < 0) { 
     printf("Connect error\n"); 
     fflush(stdout); 
     return 0; 
    } 
    char chunkStr[128]; 
    pthread_mutex_lock(&lock1); 
    int chunkNum = nextChunk++; 
    pthread_mutex_unlock(&lock1); 
    sprintf(chunkStr,"%d",chunkNum); 
    send(con_fd,chunkStr,128,0); 
    sizeRec = recv(con_fd,buf,1024,0); 
    printf("Size of chunk %d received by %lu on port %d: %d bytes\n",chunkNum,pthread_self(),conn->port,sizeRec); 
    if (sizeRec <= 0) { 
     return 0; 
    } 
} 
/*FILE *f = fopen(filename, "w"); 
if (!f) { 
    printf("Can't open %s for input. Program halting\n",filename); 
    exit(0); 
}*/ 
/*while ((sizeReceived = recv(sock,buf,1024,0)) > 0) { 
    if (fwrite(buf,sizeof(char),sizeReceived,f) == -1) { 
     printf("Error writing file"); 
     exit(0); 
    } 
} 
fclose(f);*/ 
close(con_fd); 
return 0; 
} 

int main(int argc, char ** argv) { 

if (argc < 3 || argc % 2 == 0) { 
printf("Usage: ./client <ipaddr1> <port1> <ipaddr2> <port2> . . .\n"); 
return -1; 
} 
int numThreads = argc/2; 
pthread_t threads[numThreads]; 
struct connection** connections = malloc(sizeof(struct connection*)*numThreads); 
//char* args[numThreads][2]; 
printf("numThreads: %d\n",numThreads); 
for (int i=0; i<numThreads; i++) { 
    connections[i] = malloc(sizeof(struct connection)); 
    connections[i]->ipAddr = argv[2*i+1]; 
    connections[i]->port = atoi(argv[2*i+2]); 
    printf("port number: %d\n",connections[i]->port); 
    pthread_create(&threads[i], NULL, getFile, (void*)(connections[i])); 
} 
for (int i=0; i<numThreads; i++) { 
    free(connections[i]); 
    pthread_join(threads[i], NULL); 
} 
pthread_mutex_destroy(&lock1); 
return 0; 
} 
+0

你不應該試圖'printf' pthread_self'的'的返回值。你的問題可能在其他地方,但這是首先看的好地方。 – jerry 2013-04-21 19:19:31

回答

1

你的主要問題是main()第二for循環。

您首先釋放數據結構,然後致電pthread_join()。反過來這兩個陳述,它應該工作可靠。

如果您使用Linux,我建議使用valgrind工具,這很容易有助於發現這些問題。對於Windows我只知道做同樣的昂貴的商業工具(如Purify)。

+0

我們在班上了解到Valgrind,我一直在使用它。在使用Valgrind時,我發現了你指出的錯誤,在某些情況下我在訪問它之前肯定釋放了內存,所以非常感謝您指出了這一點。事實證明,這並沒有解決我遇到的問題。如果以後有人發現這個問題,我通過用「char * chunkStr = calloc(sizeof(char),128)替換」char chunkStr [128]「來解決這個問題。我不確定爲什麼,但是這樣做有點影響輸出 – user2271605 2013-04-22 02:11:23

+0

用堆變量替換堆棧變量只會移動存儲位置,如果這會影響程序行爲,那麼您的問題仍然存在(可能是某種緩衝區溢出 - 但讀取代碼我沒有看到任何理由)在我的測試中,打印與所建議的更改一起工作,但我只做了一個簡單的I/O測試。再次,valgrind和gdb一起非常適合尋找此類問題。:-) – 2013-04-22 08:00:59

+0

@ user2271605 the line'send (con_fd,chunkStr,128,0);'在訪問未初始化的數據,因爲它發送了所有128個字節,但是設置的數量要少得多(使用'sprintf(chunkStr,「%d」,chunkNum);')雖然這是未定義的行爲理論上可以做任何事情,我同意德克的觀點,即如果這樣做能解決這個問題,那麼你也可能會這樣做某處有另一個錯誤。可能是不相關的,但是你也試圖使用'%d'打印一個'ssize_t',你應該爲你的庫使用正確的格式字符串(例如'%zd')。 – jerry 2013-04-22 12:38:18

0

更改此:

for (int i=0; i<numThreads; i++) { 
    free(connections[i]); 
    pthread_join(threads[i], NULL); 

要:

for (int i=0; i<numThreads; i++) { 
    pthread_join(threads[i], NULL);   
    free(connections[i]); 
+0

感謝您的注意。那個錯誤導致了我在Valgrind發現的內存問題,但不幸的是我沒有遇到這個錯誤。 – user2271605 2013-04-22 02:18:13

相關問題