开发者

Program misbehaves 25% of the time

Inspired by this topic, I decided to write a simple program that does exactly that.

The logic isn't complicated and I have a working program 75% of the time.. The amount of asked numbers is defined as #define BUFSIZE x, where x can be an arbitrary int.

The problem arises when ((BUFSIZE+1) % sizeof(int)) == 0.

So for example, if BUFSIZE=10, my program behaves correctly, when BUFSIZE=11 I get odd 开发者_运维知识库behaviour.

Here is the sourcecode:

#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 7

int max(int *buf);

int main()
{
    int bufsize = BUFSIZE, *buf = malloc(sizeof(int[bufsize]));

    // read values
    int *ptr = buf;
    while(--bufsize + 1)
    {
        printf("Input %d: ", BUFSIZE - bufsize);
        scanf("%d", ptr);
        ++ptr;
    }

    // reset pointer and determine max
    ptr = buf;
    printf("\nMax: %d\n", max(ptr));
    // cleanup
    free(buf);
    ptr = NULL;
    buf = NULL;

    exit(EXIT_SUCCESS);
}

int max(int *buf)
{
    int max = 0;
    while(*buf)
    {
        printf("%d\n", *buf);
        if(*buf > max) max = *buf;
        ++buf;
    }
    return max;
}

And some sample output for BUFSIZE=2 (correct) and BUFSIZE=3 (incorrect).

suze:/home/born05/htdocs/experiments/c# gcc input.c && ./a.out
Input 1: 12
Input 2: 23
12
23

Max: 23

suze:/home/born05/htdocs/experiments/c# gcc input.c && ./a.out
Input 1: 12
Input 2: 23
Input 3: 34
12
23
34
135153

Max: 135153

I have the feeling it is something extremely logical but I can't put my finger on the exact cause of this misbehaviour. Could someone point out the (perhaps obvious) flaw to me?


It's actually pure luck that this even works for any values of BUFSIZE. (In fact, for me, it breaks on BUFSIZE=2). Here's why -- this:

while(*buf)

Is not an appropriate way to check for the end of your buffer. What this does is load the value at the address pointed to by buf and see if the contents are zero. Since you're never explicitly putting a zero at the end of your buffer, that's never necessarily going to be true, and that loop could run potentially forever, reading into memory that is past the end of your buf array and invoking undefined behavior.

You either need to allocate an extra element at the end of the buf array and set it to zero (but then your program won't work right if the user enters 0 as input), or explicitly pass the size of buf to the max function and use that to determine when you should stop looping.


This

int bufsize = BUFSIZE, *buf = malloc(sizeof(int[bufsize]));

should be

int bufsize = BUFSIZE, *buf = malloc(sizeof(int[BUFSIZE + 1]));
buf[BUFSIZE] = 0;

In your current code you allocate memory for one integer (sizeof(int[bufsize]) evaluates to sizeof(int*)), instead you need memory for BUFSIZE integers and one extra integer containing null afterwards.

In your current code you have so-called undefined behavior - you use memory not legally allocated to you. In your case it sometimes works sometimes not. Well, at least you know it right now, not when it is pushes to control a nuclear power plant.


You're treating buf as if it was a null terminated string array. You could do that if your data values are guaranteed never to be zero and you actually put the zero there (which your program isn't doing).

Rather try changing your max() function to something like this (adjusting prototype and calling location accordingly):

int max(int *buf, int count)
{
    int max = 0;

    // Check inputs
    if (buf == NULL || count <= 0)
    {
        printf("max(): bad parameter(s)\n");
        return 0;
    }

    while(count--)
    {
        printf("%d\n", *buf);
        if(*buf > max) max = *buf;
        ++buf;
    }
    return max;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜