-1

I am trying to use atof() to convert a string to a double (obviously), but the results are not what I expect. Here is the code and debug information about the variable values BEFORE atof():

d = atof (arg);
next.db = d;

*debug info*
arg = 0x0034f7b0 "10.0"
d = 0.0000000000000000

Once the program has stepped through atof(). the results are as follows:

arg = 0x0034f7b0 "ôþSÄ÷4"
d = 0.0000000000000000

As you can see, before the command, the arg variable does hold a valid double. Though, the return value is 0. What confuses me, is why does the value of arg change?

Also, I do have stdlib.h included. As well, arg is declared as:

char *arg;

If it helps at all, the "10.0" was read from a file.

More code:

void read_instructions()
{
    char *str;
    char *arg;
    int n;
    char c;
    double d = 0;
    instruction next = {0};

    while (!feof(datafile)) {
        // Fetch the next string
        // if (push or pop), get the next argument
        // create instructiwn and add to instruction array
        str = get_next_string();

        if (strncmp (str, "P", 1) == 0) {
            if (strncmp (str, "PUSH", 4) == 0) {
                next.func = pushFunc;
            }
            else {
                next.func = popFunc;
            }
            arg = get_next_string();
            n = arg[0];
            if (n > 64 && n < 71)
                next.ch = arg[0];
            else {
                d = atof (arg);
                next.db = d;
            }
            instr[instr_count] = next;
            instr_count++;
        }
    else {
        c = str[0];


        switch (c) {
        case 'A' :
            next.func = addFunc;
            break;
        case 'S' :
            next.func = subFunc;
            break;
        case 'M' :
            next.func = multFunc;
            break;
        case 'D' :
            next.func = divFunc;
            break;
        case 'H' :
            next.func = haltFunc;
        default :
            printf ("Invalid instruction");
        }
        instr[instr_count] = next;
        instr_count++;
    }
}
fclose (datafile);
}

This is the given code to open and access the file:

FILE *datafile;


int main(int argc, char *argv[]) 
{
    if (argc != 2) {
        printf("error, incorrect number of arguments");
        haltFunc(instr[0]);
    }

    open_file(argv[1]);
    read_instructions();
    execute_instructions();
    return 0;
}

void open_file(char* argv) 
{
    char buf[1024];
    char cwd[512];

    getcwd(cwd, sizeof cwd);
    sprintf(buf, "%s\\%s", cwd, argv);

    if (!(datafile = fopen(buf, "r"))) {
        printf("Error: Make sure your file is located here:\n%s", buf);
    }
}

char* get_next_string() 
{
    char str[15];

    fscanf(datafile, "%s", &str);

    return str;
}

The header file:

#ifndef MAIN_HEADER_H
#define MAIN_HEADER_H

#define INSTR_SIZE 30

typedef struct {
    void (*func)(instruction);
    union {
        double db;
        char ch;
    };
} instruction;

int main(int, char*);
char* get_next_string();
void open_file(char*);
void read_instructions();
void execute_instructions();
void pushFunc(instruction instr);
void popFunc(instruction instr);
void addFunc(instruction instr);
void subFunc(instruction instr);
void multFunc(instruction instr);
void divFunc(instruction instr);
void haltFunc(instruction instr);

#endif

And this is the test file:

PUSH 10.0
PUSH 4.0
PUSH 7.0
PUSH 5.0
POP D
POP E
POP 
PUSH D
ADD
PUSH 5.0
POP B
PUSH 17.0
POP E
PUSH B
PUSH E
SUB
HALT
Troncoso
  • 2,343
  • 3
  • 33
  • 52
  • Can you show the whole code? It is likely you overwrite something there. – nhahtdh Jul 11 '12 at 02:50
  • Overwritting what? The only thing involved is that variable and function call. – Troncoso Jul 11 '12 at 03:06
  • 1
    I'm not sure. The code that you show doesn't seem to have any problem. Give us some code that we can reproduce the effect. – nhahtdh Jul 11 '12 at 03:10
  • 3
    Please show a small complete program that exhibits the problem. Does [this program](https://gist.github.com/3087729) work for you? – Keith Thompson Jul 11 '12 at 03:10
  • What's the encoding of the file? – Eric Finn Jul 11 '12 at 03:14
  • Disable optimization and try again. The compiler is playing tricks like throwing away the "arg" variable since you aren't using it any more. – Raymond Chen Jul 11 '12 at 03:15
  • I added the entire method to the end of the involved if statement. The file is kind of long, so I'm trying to avoid posting what I don't need. As well, I don't know what you mean by "encoding" and how would I turn off optimization in VS? – Troncoso Jul 11 '12 at 03:21
  • Also, the program compiles and runs, but I get the wrong value for that double. Everything up to the atof function call works appropriately. The debug information is directly from the debugger. – Troncoso Jul 11 '12 at 03:25
  • @Troncoso - I'll bet anything that the program posted by Keith Thompson works for you. So: There's something wrong with your *program* that makes this happen (not with atof for sure). And we cannot guess what is until you post an example that reproduces it for us. Try to strip parts away from your program, like getting rid of file I/O, and replacing it with a string, etc, using a smaller input, etc, until you have something small enough to post which *still* causes a problem for you. This might actually help you fix the problem yourself because you'll see more clearly what went wrong. – ArjunShankar Jul 11 '12 at 07:34
  • Yes his program does with. The issue with your suggested debugging process is that I was provided some of the code. All of the file I/O is already provided. What I posted is all that I've written. I'll see what I can do about it though. – Troncoso Jul 11 '12 at 14:38
  • I put a test immediately after reading a string from the file that prints the string. Before printing, the string holds the correct value, but after using puts() to print it, strange characters are appended. So for str = get_next_string(), The string returned is "PUSH" but the string printed is "PUSHÄþS". This is also the new value in str. I believe that should be enough to reproduce the problem. I don't even get as far as the execute_instructions() so that can be omitted. – Troncoso Jul 11 '12 at 14:48
  • `atof()` does not return any error, try using `strtod()` instead which sets errno and see if that helps you come closer to your problem. – Jite Jul 11 '12 at 14:53

1 Answers1

2

Your problem is probably caused by the get_next_string() function returning a pointer to a temporary local character array. As soon as the function returns, the stack memory once used by str[] is being overwritten by some other automatic variable. That would explain why arg is being corrupted.

There are several possible fixes.

  • The caller could allocate memory to hold the string and pass this pointer to the function for it to fill with data.
  • The callee could allocate memory for the string and return that pointer. That also returns ownership to the caller and responsibility for calling free() when done.
  • The str[] array could be declared static inside the function. It would no longer be temporary but be aware that every time you call the function the previous string will be overwritten.
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70