簡體   English   中英

C : printf 以混合順序打印變量

[英]C : printf printing variables in the mixed order

這是我的代碼,

#include <time.h>
#include <pthread.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>

unsigned sleep(unsigned sec) ;

void get_time(char *buf) {  
    time_t t = time(NULL) ;
    struct tm tm = *localtime(&t) ;
    sprintf(buf,"%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec) ;
}

void *calculateSize(uint64_t size, char *buf) {   
    if (size < 1024ULL){
        sprintf(buf, "%.1f %s", (float) size, "B") ;
        return NULL ;
        }    
    else if (size < (1024 * 1024)) {
        sprintf(buf, "%.1f %s", (float) size/1024ULL, "KiB") ;
        return NULL ;
    } 
    else if (size > (1024 * 1024)) {
        sprintf(buf, "%.1f %s", (float) size/(1024ULL * 1024ULL), "MiB") ;
        return NULL ;
    } 
    strcpy(buf, "0") ;
    return NULL ; 
}

void * run(char *interface, char * download_buf, char * upload_buf) {
    unsigned long rdiff,tdiff ;
    unsigned long rx_old,rx_new ;
    unsigned long tx_old,tx_new ;
    char buf[10] ;
    char rx_file[512] ;
    char tx_file[512] ;
    sprintf(rx_file, "/sys/class/net/%s/statistics/rx_bytes", interface) ;
    sprintf(tx_file, "/sys/class/net/%s/statistics/tx_bytes", interface) ;
    
    FILE *rf = fopen(rx_file,"r") ;
    FILE *tf = fopen(tx_file,"r") ;
    
    if (rf != NULL && tf != NULL) {
        fscanf(rf,"%lu", &rx_old) ;
        fscanf(tf,"%lu", &tx_old) ;
        
        fclose(rf) ;
        fclose(tf) ;
    }
    else {
        return NULL ;   
    }
    
    sleep(1) ;
    
    rf = fopen(rx_file,"r") ;
    tf = fopen(tx_file,"r") ;
    
    if (rf != NULL && tf != NULL) { 
        fscanf(rf,"%lu", &rx_new) ;
        fscanf(tf,"%lu", &tx_new) ;
    
        rdiff = rx_new - rx_old ;
        tdiff = tx_new - tx_old ;                       
                
        fclose(rf) ;
        fclose(tf) ;
    }
        
    else {
        return NULL ;   
    }
    calculateSize(rdiff,buf) ;
    strcpy(download_buf,buf) ;
    calculateSize(tdiff,buf) ;
    strcpy(upload_buf,buf) ;
    return NULL ;
}

void *net_speed(void *thread_speed_args ) {
        char* iface = *(char **)thread_speed_args ;
        char carrier_file[512] ;
        sprintf(carrier_file,"/sys/class/net/%s/carrier", iface) ;
        printf("Reading from %s\n", carrier_file) ;
        while(1) {
                if( access( carrier_file, F_OK ) == 0 ) {
                    run(iface, ((char **)thread_speed_args)[1], ((char **)thread_speed_args)[2]) ;
                    } 
            else {
            sprintf(((char **)thread_speed_args)[1],"000 B") ;
            sprintf(((char **)thread_speed_args)[2],"000 B") ;
                sleep(1) ;
                    }
        }
        return NULL ;    
}

int main(int argc, char *argv[]) {
    char time_buf[10] ; //hh:mm:ss : 8 char + 1 null terminator char
    char download_buf[8],upload_buf[8] ;
    char* thread_speed_args[3] = { argv[1], download_buf, upload_buf } ;
    
    pthread_t thread_speed ;
    pthread_create(&thread_speed, NULL, net_speed, thread_speed_args) ;
    pthread_detach(thread_speed) ;
    
    while(1){
        get_time(time_buf) ;
        printf("Down:%s Up:%s %s\n", thread_speed_args[1], thread_speed_args[2], time_buf) ;
        fflush(stdout) ;
        sleep(1) ;
    }
}

我正在使用線程持續監控接口上的無線數據傳輸速率,我還打印了傳輸速率的時間。 我只是在試驗線程,如果我的編程邏輯不好,請原諒我。

我注意到,當我進行速度測試時,輸出或打印變得一團糟,如下所示

Down:0.0 B Up:0.0 B 23:49:03
Down:0.0 B Up:0.0 B 23:49:04
Down:0.0 B Up:0.0 B 23:49:05
Down:17.0 KiB9.2 KiB Up:9.2 KiB 23:49:06
Down:5.3 KiB Up:6.5 KiB 23:49:07
Down:3.4 KiB Up:4.1 KiB 23:49:08
Down:400.6 Ki20.3 KiB23:49:09 Up:20.3 KiB23:49:09 23:49:09
Down:918.6 Ki49.6 KiB23:49:10 Up:49.6 KiB23:49:10 23:49:10
Down:912.8 Ki53.5 KiB23:49:11 Up:53.5 KiB23:49:11 23:49:11
Down:959.2 Ki32.2 KiB23:49:12 Up:32.2 KiB23:49:12 23:49:12
Down:711.5 Ki33.8 KiB23:49:13 Up:33.8 KiB23:49:13 23:49:13

看到最后幾行了嗎?

誰能告訴我這里發生了什么? 我該如何糾正?

發生這種情況是因為您同時訪問多個線程中的公共資源 - 在本例中為 STDOUT 句柄。 將信息輸出到控制台時,您需要同步線程 - 最簡單的方法是使用互斥鎖。 你可以在這里閱讀更多。

雖然您的線程缺乏任何類型的同步(在極少數情況下會隨機混淆您的輸出),但這甚至不是您的問題。

這是你的問題:

char download_buf[8],upload_buf[8] ;

char buf[10] ;
strcpy(download_buf,buf) ;
strcpy(upload_buf,buf) ;

您正在將最多 9 個字符的字符串復制到 7 個字符的字符串中,從而溢出緩沖區。 並且由於緩沖區碰巧在堆棧上彼此相鄰,因此第二個 strcpy 將覆蓋第一個字符串的 0 終止符。 與覆蓋第二個字符串的 0 終止符的 time_buf 相同。

總體而言,由於緩沖區溢出導致了很多未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM