Thread: function with variable arguments crashes

  1. #1
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    86

    function with variable arguments crashes

    The following program compiles with no errors. If left as is, it will execute with no apparent errors.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    
    #define ARGCNT 5
    
    void show_array(const double * array, int num);
    double * new_d_array(int num, ...);
    
    int main(void)
    {
    	double * p1;
    
    	p1 = (double *) malloc(ARGCNT * sizeof(double));
    
    	p1 = new_d_array(ARGCNT, 1.2, 2.3, 3.4, 4.5, 5.6);
    
    	show_array(p1, ARGCNT);
    
    	free(p1);
    
    	puts("Goodbye!");
    
    	return 0;
    }
    
    void show_array(const double * array, int num)
    {
        int ct;
    
        for (ct = 0; ct < num; ct++)
            printf("%.2lf ", array[ct]);
    
        putchar('\n');
    }
    
    double * new_d_array(int num, ...)
    {
    	int ct;
    	double * array;
    	va_list holder;
    	va_start(holder, num);
    	
    	for (ct = 0; ct < num; ct++)
    		array[ct] = va_arg(holder, double);   // crashes HERE
    
    	va_end(holder);
    	
    	return &array[0];
    }
    The behavior I don't understand is: when I change the line
    Code:
    p1 = new_d_array(ARGCNT, 1.2, 2.3, 3.4, 4.5, 5.6);
    to include more (or fewer) arguments, the program crashes at the commented spot. I am of course changing the body of ARGCNT to reflect the addition (or subtraction) of double values. It doesn't seem to matter.

    To make this even more interesting, if I leave the five double values as they are, but change the ARGCNT body to any number above or below 5, it will still run fine, but will truncate or add on output as expected. The added output (above 5 arguments) will be zeroed out double values, but it will still process and print them.

    Where is the problem???
    V8 Interceptor: KDE 5.25.5 on Manjaro Linux 22.0.0 "Sikaris"
    Steering wheel: gcc 12.2.0 in Kate
    Supercharger: NASM 2.15.05
    Engine: AMD Ryzen 7 1700
    Dashboard: NVIDIA GeForce GTX 1060 6GB
    Rusty old trailer for hauling 3% of my Steam catalog: Windows 7 Pro 64bit SP1
    3 Antique Ford Model T automobiles for vintage LAN gaming: Windows XP SP3
    Sturdy buckboard for DOS LAN gaming: DOSBox 0.74-3 on Windows XP SP3

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Where's your memory allocation for array? Try changing the definition to:
    Code:
    double *array = malloc(sizeof(double) * num);
    Don't forget to free() the memory in the calling function somewhere.
    If you understand what you're doing, you're not learning anything.

  3. #3
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    86
    Crap! Memory allocation again... and I was trying to be mindful of it.

    The mistake I made was assuming I only had to use malloc() for the pointer in main(). I never even considered I'd need to do the same allocation in the called function as well!

    Thanks!!!
    V8 Interceptor: KDE 5.25.5 on Manjaro Linux 22.0.0 "Sikaris"
    Steering wheel: gcc 12.2.0 in Kate
    Supercharger: NASM 2.15.05
    Engine: AMD Ryzen 7 1700
    Dashboard: NVIDIA GeForce GTX 1060 6GB
    Rusty old trailer for hauling 3% of my Steam catalog: Windows 7 Pro 64bit SP1
    3 Antique Ford Model T automobiles for vintage LAN gaming: Windows XP SP3
    Sturdy buckboard for DOS LAN gaming: DOSBox 0.74-3 on Windows XP SP3

  4. #4
    Novice
    Join Date
    Jul 2009
    Posts
    568
    You could also pass in a pointer to memory malloc()'ed in main.

    Do note that you only need to malloc() in either main() or new_d_array(). If you malloc() for double *p1 in main(), then malloc() again in new_d_array() for double *array and assign the return value of new_d_array() to double *p1, you will forever lose access to memory you malloc()'ed for double *p1 initially. You now have no references to that memory and are therefor unable to free it. Thus a memory leak is born!

  5. #5
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    86
    So should I have used malloc() only in new_d_array()?

    After itsme86's reply, I used malloc() to declare the array pointer as per his suggestion, and the program worked. After reading your response, I'm thinking I should have never used malloc() with p1 in main() in the first place.

    Due to your new information regarding memory leaks, I removed the malloc() use in main() and recompiled, and everything still works.

    If I merely declare p1 this way in main():

    Code:
    double * p1;
    and refrain from using malloc() until new_d_array(), then does this code (before the return statement in main()):

    Code:
    free(p1);
    free up the memory originally allocated for array in new_d_array()? If so, is it because p1 is now pointing to the same address that the allocated memory began at in the first place?
    V8 Interceptor: KDE 5.25.5 on Manjaro Linux 22.0.0 "Sikaris"
    Steering wheel: gcc 12.2.0 in Kate
    Supercharger: NASM 2.15.05
    Engine: AMD Ryzen 7 1700
    Dashboard: NVIDIA GeForce GTX 1060 6GB
    Rusty old trailer for hauling 3% of my Steam catalog: Windows 7 Pro 64bit SP1
    3 Antique Ford Model T automobiles for vintage LAN gaming: Windows XP SP3
    Sturdy buckboard for DOS LAN gaming: DOSBox 0.74-3 on Windows XP SP3

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    As they said, just malloc it ONE time - it doesn't matter where, BUT if you malloc it outside main(), then you need to bring the address back to main(), as you are now doing, in new_d_array().

    Whatever you decide, but just malloc the array ONE time. You don't ever want two arrays with the same name, btw.

    It's not unusual to have a program "work" in C, just fine, despite obvious bugs, (especially if it's a small program, using small amounts of data). C doesn't guarantee to crash your program, just because you forgot to give some memory to something that needed it.

    You are assigning the address from the array, to p1, when control returns from new_d_array function. Just remove that malloc() in main(), and you should be good to go.

  7. #7
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Quote Originally Posted by spongefreddie View Post
    If I merely declare p1 this way in main():

    Code:
    double * p1;
    and refrain from using malloc() until new_d_array(), then does this code (before the return statement in main()):

    Code:
    free(p1);
    free up the memory originally allocated for array in new_d_array()? If so, is it because p1 is now pointing to the same address that the allocated memory began at in the first place?
    Only if you somehow made it a pointer to the memory malloc()'ed in new_d_array().

    I.e. you did something like this:
    Code:
    ...
    double *p1;
    ...
    p1 = new_d_array();
    ...
    free( p1 );
    ...
    Your take-away from this should be that (1) malloc()'ed memory is global to the process, (2) references (pointers) to this memory follow normal scoping rules.

  8. #8
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    86
    Adak, msh and itsme86:

    Thanks a ton! All my questions were answered, and more importantly, I think I now properly understand the rules regarding malloc() and free() as applied to this type of scenario.

    sf
    V8 Interceptor: KDE 5.25.5 on Manjaro Linux 22.0.0 "Sikaris"
    Steering wheel: gcc 12.2.0 in Kate
    Supercharger: NASM 2.15.05
    Engine: AMD Ryzen 7 1700
    Dashboard: NVIDIA GeForce GTX 1060 6GB
    Rusty old trailer for hauling 3% of my Steam catalog: Windows 7 Pro 64bit SP1
    3 Antique Ford Model T automobiles for vintage LAN gaming: Windows XP SP3
    Sturdy buckboard for DOS LAN gaming: DOSBox 0.74-3 on Windows XP SP3

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  3. dllimport function not allowed
    By steve1_rm in forum C++ Programming
    Replies: 5
    Last Post: 03-11-2008, 03:33 AM
  4. Variable number of arguments in function.
    By kamoda_pawel in forum C Programming
    Replies: 1
    Last Post: 01-18-2007, 07:18 AM
  5. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM