0

I wrote a merge sort. When I changed the 35 lines of code to malloc(NULL), I found that the program could still sort the results without reporting an error. Why is this happening?

There is a warning at malloc(NULL) but no error.

int sort(int*a,int n){
    int *p=(int *)malloc(NULL);
    g_sort(a,0,n-1,p);
    return 1;
}

The code can be run to sort the correct result:

#include<bits/stdc++.h>
using namespace std;
void m_qsort(int *a,int left,int mid,int right,int*temp){
    int m=mid;int r=right;
    int k=0,j=mid+1;;
    int l=left;
    while(l<=m && j<=r){
        if(a[l]<=a[j])
            temp[k++]=a[l++];
        else
            temp[k++]=a[j++];
    }
    while(l<=mid){
        temp[k++]=a[l++];
    }
    while(j<=r){
        temp[k++]=a[j++];
    }
    for(int i=0;i<k;i++){
        a[left+i]=temp[i];
    }
    
}
void g_sort(int *a,int left,int right,int*temp){
    if(left<right){
        int mid=(left+right)>>1;
        g_sort(a,left,mid,temp);
        g_sort(a,mid+1,right,temp);
        m_qsort(a,left,mid,right,temp);
        
    }

}
int sort(int*a,int n){
    int *p=(int *)malloc(NULL);
    g_sort(a,0,n-1,p);
    return 1;
}
int main()
{  
    int a[22]={8,4,7,5,6,2,1,7,10,25,0,1,75,52,14,56,33,24,852,20,26,41};
    sort(a,22);
    for(int i=0;i<22;i++){
        cout<<a[i]<<' '<<endl;
    }
}

Result:

$g++ -o main *.cpp
main.cpp: In function ‘int sort(int*, int)’:
main.cpp:46:27: warning: passing NULL to non-pointer argument 1 of ‘void* malloc(size_t)’ [-Wconversion-null]
  int *p=(int *)malloc(NULL);
                           ^
$main
0 
1 
1 
2 
4 
5 
6 
7 
7 
8 
10 
14 
20 
24 
25 
26 
33 
41 
52 
56 
75 
852 
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
459zyt
  • 31
  • 4
  • 1
    If you get in a car and turn on the ignition, why does the car start even though you don't know who's it is, you don't have a driver's license, and don't know how to drive? It is undefined behavior if you make it through your adventure with no one the wiser, or in jail, or in the hospital, or in the cemetery. A variety of things can happen when you purposely do something wrong. You can't count on just what the outcome will be. – Avi Berger Oct 07 '22 at 04:36
  • 1
    Behavior of `malloc(0)` is [implementation defined](https://en.cppreference.com/w/c/memory/malloc). – Dúthomhas Oct 07 '22 at 05:00
  • @Dúthomhas Dereferencing the returned pointer, on the other hand, is always wrong. – Avi Berger Oct 07 '22 at 05:05
  • @AviBerger ...as stated in the linked docs. – Dúthomhas Oct 07 '22 at 05:10
  • https://en.cppreference.com/w/cpp/language/ub – Jesper Juhl Oct 07 '22 at 10:01
  • 1
    [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Jesper Juhl Oct 07 '22 at 10:02
  • 1
    [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Jesper Juhl Oct 07 '22 at 10:03
  • Also, the definition of `NULL` is [implementation defined](https://en.cppreference.com/w/cpp/types/NULL). If, like in our code base, `NULL` is defined as `nullptr`, your `malloc(NULL)` would not have compiled and that is good. Never use `NULL` when an integer is expected. – prapin Oct 07 '22 at 10:50

1 Answers1

3

According to this documentation, requesting a 0 size as you did is implementation-defined. Your system's implementation probably returns a non-null pointer, because a null pointer would segfault on most systems (see Scheff's Cat's comment below for why I say "most"). The documentation says not to use this pointer, so you're violating malloc's contract. I take it that your question is for your curiosity.

Maybe it's returning an address within the heap, and your program is buffer-overrunning into adjacent virtual memory addresses that were allocated to your process. You may be able to use heap analysis tools to confirm this. This StackOverflow question has answers with some heap analysis tools.

  • 3
    To count on the fact that dereferencing a `nullptr` will seg-fault can fool you. This will working on a PC and probably on the most other major platforms. I was counting on this as well - though that's 20 years or so ago. And then I was working on Irix with MIPS CPUs. On that platform, access to a `NULL` pointer was _not_ a seg-fault. I wasn't aware of this until I compiled and ran my same code on a PC with Linux... – Scheff's Cat Oct 07 '22 at 05:24
  • Thanks for sharing! I'll edit my answer to include this. – Chris Anthony Oct 07 '22 at 05:30