Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: Code behaving differently on two systems, any idea why?

  1. #1
    Join Date
    Dec 2007
    Location
    California
    Beans
    4,958
    Distro
    Ubuntu 16.04 Xenial Xerus

    Code behaving differently on two systems, any idea why?

    So I wrote this program for class, compiled under Ubuntu using gcc 4.6.3, and for windows I compiled using mingw gcc 4.8.1, I have it working correctly and submitted, but I'm wondering why it isn't 100% in place portable as I would expect?

    I'm having a for loop count differently on XP than it counts on Ubuntu, under xp I have to subtract one from count to get a correct count, under Ubuntu (as I would expect) I have to add one.

    Here's the code, along with compile commands.

    Code:
    /* Reads from stdin and prints the c code to create a typedef struct header file
     *
     * @author 	Jeremy Jones
     * Course: 	COMS B25
     * Created: 	Nov 7, 2013
     * Source File:	createStruct.c
     */
    
    #include<stdio.h>
    #include<stdlib.h>
    
    int main(void) {
    
    	char str1[1100][64], str2[1100][64];
    	double num[1100];
    	int numElem = 0;
    	
    	puts("typedef struct {");
    	puts("\tchar *sender, *reciever;");
    	puts("\tdouble amount;");
    	puts("} Transaction;");
    	puts("");
    	puts("Transaction transactions[] = {");
    
    	int i = 0;
    	while ( EOF != scanf("%64s%64s%lf", str1[i], str2[i], &num[i]) ) {
    		numElem = i + 1;
    		i++;
    	}
    
    	for ( i = 0; i < (numElem - 1); i++ ) {
    		printf("{\"%s\", \"%s\", %f},\n", str1[i], str2[i], num[i]);
    	}
    	printf("{\"%s\", \"%s\", %f}\n", str1[numElem - 1], str2[numElem - 1], 
    			num[numElem - 1]);
    	puts("};");
    }
    This one performs as expected on both OS's compiled and ran via a simple:
    Code:
    gcc createStruct.c -o createStruct
    ./createStruct < transactions.txt > transactions.h
    Code:
    /* Searches a structure for names and computes change
     *
     * @author 	Jeremy Jones
     * Course: 	COMS B25
     * Created: 	Nov 7, 2013
     * Source File:	processTransactions.c
     */
    #include "transactions.h"
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
    	char name[64];
    	double netChange = 0;
    	int count = 0;
    	for (int i = 0; (transactions[i].reciever); ++i) {
    		count = i + 1; // on windows I have to use i - 1 to get correct count
    	}
    	printf("Number of transactions = %d\n", count);
    	printf("%s", "Enter name: ");
    	scanf("%63s", name);
    	for (int i = 0; i < count; i++) {
    		if (!strcmp(name, transactions[i].sender)) {
    			netChange -= transactions[i].amount; 
    		} else if (!strcmp(name, transactions[i].reciever)) {
    			netChange += transactions[i].amount;
    		}
    	}
    	printf("Net change for %s is %.2f\n", name, netChange);
    }
    This one counts the elements in the structure differently depending on os. Compiled and ran
    Code:
    gcc -std=c11 processTransactions.c -o processTransactions
    ./processTransactions
    Any idea *why* they run differently? Is it something I'm doing?
    Last edited by jerome1232; November 8th, 2013 at 04:53 AM.
    "You can't expect to hold supreme executive power just because some watery tart lobbed a sword at you"

    "Don't let your mind wander -- it's too little to be let out alone."

  2. #2
    Join Date
    Feb 2007
    Location
    West Hills CA
    Beans
    10,048
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Code behaving differently on two systems, any idea why?

    gcc compilers are a black box. It could be that the NSA likes to sniff a loop every now and then.

    The only thing I can think of is an extra return or line feed when going from linux to Windows, which the compiler interprets as a different instruction. Do a careful comparison of the code between the two operating systems and look at the end-of-line characters.

    I would research and summarize the differences between gcc 4.6.3 and 4.8.1 and see if that gives a clue as to what to examine next.

    Finally, are there optimization differences between the two compilers? Perhaps there is a default optimization level for each compiler that is causing different executions.
    -------------------------------------
    Oooh Shiny: PopularPages

    Unumquodque potest reparantur. Patientia sit virtus.

  3. #3
    Join Date
    Dec 2007
    Location
    California
    Beans
    4,958
    Distro
    Ubuntu 16.04 Xenial Xerus

    Re: Code behaving differently on two systems, any idea why?

    I did install gcc 4.8.1 for Ubuntu and compiled with that, still the same results. I'll have to do more poking tomorrow, the only difference between the generated header files is the line endings.

    Code:
    **Windows**
    cat -v -e transactions.h | tail
    {"Isabella", "Emma", 628.280000},^M$
    {"Abigail", "Sophia", 852.930000},^M$
    {"Anthony", "Alexander", 264.010000},^M$
    {"Mia", "Emily", 36.110000},^M$
    {"Ethan", "Jacob", 767.720000},^M$
    {"Ethan", "Noah", 782.250000},^M$
    {"Daniel", "Mia", 839.960000},^M$
    {"Jayden", "Daniel", 233.540000},^M$
    {"Anthony", "Emma", 603.880000}^M$
    };^M$
    
    **Ubuntu**
    cat -v -e transactions.h | tail
    {"Isabella", "Emma", 628.280000},$
    {"Abigail", "Sophia", 852.930000},$
    {"Anthony", "Alexander", 264.010000},$
    {"Mia", "Emily", 36.110000},$
    {"Ethan", "Jacob", 767.720000},$
    {"Ethan", "Noah", 782.250000},$
    {"Daniel", "Mia", 839.960000},$
    {"Jayden", "Daniel", 233.540000},$
    {"Anthony", "Emma", 603.880000}$
    };$
    I converted the line endings on each operating system and I still get the same results. (it's a header file so I don't see how line endings would affect it anyways)
    "You can't expect to hold supreme executive power just because some watery tart lobbed a sword at you"

    "Don't let your mind wander -- it's too little to be let out alone."

  4. #4
    Join Date
    Aug 2010
    Location
    Lancs, United Kingdom
    Beans
    1,354
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Re: Code behaving differently on two systems, any idea why?

    I could be wrong here because I haven't seen enough of transactions.h, but my best guess is that
    Code:
        for (int i = 0; (transactions[i].reciever); ++i) {
    reads beyond the bounds of the transactions array because there does not exist a declared element for which reciever [sic] is 0. In that case, you have undefined behaviour.

  5. #5
    Join Date
    Aug 2011
    Location
    47°9′S 126°43W
    Beans
    2,165
    Distro
    Kubuntu 14.04 Trusty Tahr

    Re: Code behaving differently on two systems, any idea why?

    I'm with spjackson's here. I put more trust in the compiler than in my code (or yours). So it's not really a Linux/Windows problem but more a problem with your code, and you just happen to be lucky on one of the two platforms.
    Warning: unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.

  6. #6
    Join Date
    Feb 2009
    Beans
    1,468

    Re: Code behaving differently on two systems, any idea why?

    Incidentally, you usually[*] shouldn't put data (or code) in header files, because you may run into linking problems if you #include "transactions.h" in more than one location. I would put "extern Transaction transactions[];" in the header file, and have your createStruct write a .c file that #includes it. This may not be important for your current project, but it's something to be aware of.
    [*] Essentially always. I can't think of a counterexample but that might be lack of creativity on my part.

  7. #7
    Join Date
    Dec 2007
    Location
    California
    Beans
    4,958
    Distro
    Ubuntu 16.04 Xenial Xerus

    Re: Code behaving differently on two systems, any idea why?

    Well that was the assignment (to print to a header file then use the header file in a second program) and I couldn't think of any other way to count the elements of the array. That's the data we are given and we can't stick our own zero in to use as a terminator. We can't modify the structure so that it tracks it's own size. I think you are correct and I just happen to be hitting a zero in memory after the array. Data has come out correct on every run however (with the OS specific adjustment).
    "You can't expect to hold supreme executive power just because some watery tart lobbed a sword at you"

    "Don't let your mind wander -- it's too little to be let out alone."

  8. #8
    Join Date
    Aug 2010
    Location
    Lancs, United Kingdom
    Beans
    1,354
    Distro
    Ubuntu Mate 16.04 Xenial Xerus

    Re: Code behaving differently on two systems, any idea why?

    Well I don't know what is and isn't allowed by your assignment, but there are at least 3 ways you can do this.

    1. Count the records while generating the header file and print a line like "static const int array_size %d;" (or #define if you prefer).
    2. When generating the header file, write a sentinel record at the end (after EOF) "{ NULL, NULL, 0.0 }".
    3. Use the well-worn sizeof(transactions) / sizeof(transactions[0]) to limit your loop. In fact you don't need to loop through counting them because you know how many there are before you start, i.e. replace your counting loop with: count = sizeof(transactions) / sizeof(transactions[0]);

  9. #9
    Join Date
    Dec 2007
    Location
    California
    Beans
    4,958
    Distro
    Ubuntu 16.04 Xenial Xerus

    Re: Code behaving differently on two systems, any idea why?

    I should've thought of number 3. Ah well, I shouldn't get dinged too bad for the mistake. That clears it up. The mistake was me as I suspected
    "You can't expect to hold supreme executive power just because some watery tart lobbed a sword at you"

    "Don't let your mind wander -- it's too little to be let out alone."

  10. #10
    Join Date
    Feb 2009
    Beans
    1,468

    Re: Code behaving differently on two systems, any idea why?

    If that's what the instructor expects you to do, that explains why it has to be in a header file -- you can't use sizeof to learn the size of an array defined in a different file (because sizeof is evaluated at compile time, while the data may not be available until link time).

    That doesn't make it a sensible idea. A realistic C program would use a sentinel value or store the length separately. Fortunately for your instructor, academics don't need to concern themselves with such mundane trivialities as modularity and robustness.

    (Me? Why no, I'm not bitter at all. Why do you ask?)

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •