Thread: C : printf printing variables in the mixed order

  1. #1
    Registered User
    Join Date
    May 2022
    Posts
    2

    C : printf printing variables in the mixed order

    Code:
    #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) ;
        }
    I am using a thread to continuously monitor my wireless data transfer rate on an interface, I am also printing the time along with the transfer rate. I am just experimenting with threads, forgive me if my programming logic is bad.
    I notice that when I do a speed test the output or print becomes all messed up like below


    See the last few lines?
    Could anyone tell me what is happening here? How do I correct it?
    Would it have made any difference if I declared the variables outside main as global? Because in the past I wrote this code with all the printed variables outside the main and it did not have this problem.

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    See the last few lines?
    There are no lines.

    Try making download_buf and upload_buf bigger. calculateSize definitely has the potential to write more than 8 bytes to them, e.g., 123.7 KiB will write 10 bytes. There's no reason not to make them extra big, say 32 bytes.

    I don't understand the pointless void* return of calculateSize. And presumably you don't mean it to put "0" in buf if the size is exactly 1MiB, which is what it will currently do.

    You've forgotten to include stdio.h, and you shouldn't need to separately prototype sleep().
    Last edited by john.c; 05-21-2022 at 02:08 PM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    May 2022
    Posts
    2
    Sorry, I was half asleep in the night when I posted this. I did a poor job copy posting from the text editor and terminal.
    Here is the terminal output.

    Code:
    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
    I can't seem t find the edit option for my first post.

    And yes increasing size of the download_buf and upload_buf
    has seemed to make the problem go away. I also changed the function that converts bytes into human readable format.

    Code:
    #include <stdio.h>
    #include <time.h>
    #include <pthread.h>
    #include <string.h>
    #include <inttypes.h>
    #include <unistd.h>
    
    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(double size/*in bytes*/, char *buf) {
        int i = 0;
        const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
        while (size > 1024) {
            size /= 1024;
            i++;
        }
        sprintf(buf, "%.*f %s", i, size, units[i]);
    }
    
    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[16] ;
        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],"0.00 B") ;
                sprintf(((char **)thread_speed_args)[2],"0.00 B") ;
                     sleep(1) ;
                        }
            }
            return NULL ;    
    }
    
    int main(int argc, char *argv[]) {
        char time_buf[10] ; //hh:mm:ss : 8 char + 1 null terminator char + 1 extra
        char download_buf[16],upload_buf[16] ;
        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) ;
        }
    }
    Someone else told me I need mutex lock lock since my main() and the thread is sharing those variables, do I need to use a mutex lock?

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    I suppose you would need a mutex since otherwise main could be printing the values when one but not the other has been changed by the second thread, or perhaps one could have been half changed.

    I get "mismatches" from the following code when not using the mutex.
    Code:
    #define _POSIX_C_SOURCE 199309L
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <pthread.h>
     
    #define USE_MUTEX 0    // set to 1 to use mutex
     
    #if USE_MUTEX
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    #endif
    struct timespec ts1 = {0, 24390244}; // ~1/41 second
    struct timespec ts2 = {0, 23255814}; // ~1/43 second
     
    void *thread(void *args) {
        unsigned n = 1000000000;
        while (1) {
    #if USE_MUTEX
            pthread_mutex_lock(&mutex);
    #endif
            sprintf(((char**)args)[0], "%u", n);
            sprintf(((char**)args)[1], "%u", n);
    #if USE_MUTEX
            pthread_mutex_unlock(&mutex);
    #endif
            ++n;
            nanosleep(&ts2, NULL);
        }
        return NULL;
    }
     
    int main() {
        char a[32], b[32];
        char *args[2] = {a, b};
        pthread_t thr;
        pthread_create(&thr, NULL, thread, args);
        pthread_detach(thr);
        while (1) {
            nanosleep(&ts2, NULL);
    #if USE_MUTEX
            pthread_mutex_lock(&mutex);
    #endif
            unsigned long x = strtol(a, NULL, 10);
            unsigned long y = strtol(b, NULL, 10);
    #if USE_MUTEX
            pthread_mutex_unlock(&mutex);
    #endif
            if (x != y) {
                printf("MISMATCH! %lu %lu\n", x, y);
                exit(0);
            }
        }
        return 0;
    }
    Last edited by john.c; 05-23-2022 at 10:15 AM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Printing variables safely using printf, wprintw
    By wiqxlzxsxj in forum C Programming
    Replies: 7
    Last Post: 06-27-2017, 03:33 AM
  2. Printf printing twice
    By travis9090 in forum C Programming
    Replies: 4
    Last Post: 11-17-2015, 02:23 AM
  3. printf printing twice?
    By drshmoo in forum C Programming
    Replies: 5
    Last Post: 03-19-2011, 02:41 AM
  4. printf not printing
    By deadhippo in forum C Programming
    Replies: 5
    Last Post: 05-04-2008, 12:36 AM
  5. Printing out in wrong order
    By DarkDot in forum C++ Programming
    Replies: 1
    Last Post: 05-05-2007, 02:56 PM

Tags for this Thread