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
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.
Related
My code runs perfectly on my machine but it fails even in the sample testcases on Hackerrank. How can the same code yield different results on two different environment?
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
int maxum(int arr[], int n)
{
int t[100][100];
for(int i=0;i<n+1; i++)
for(int j=0; j<n+1;j++)
{
if(i==0)
t[i][j]=0;
else
t[i][j]=max(t[i-1][j]+arr[i-1], t[i-1][j] );
}
int maximum=0;
for(int i=0;i<n+1;i++)
for(int j=0; j<n+1;j++)
{
if(t[i][j]>maximum)
maximum=t[i][j];
}
return maximum;
}
int main()
{
int arr[100],i,n;
cin>>n;
for(i=0;i<n;i++)
cin>>arr[i];
cout<<maxum(arr,n);
return 0;
}
The algorithm is just wrong. For instance given the input from the first test case
5
3 7 4 6 5
The correct answer is 13 (7+6) but your code outputs 25 (3+7+4+6+5).
It seems haven't implemented the requirement that the members of the maximal subset be non-adjacent.
Your code exhibits undefined behaviour at least for larger inputs. Example:
g++ -O3 -Wall -Wextra -pedantic -std=c++17 -fno-exceptions -fsanitize=address a.cpp
yes 100 | ./a.out
Triggers asan to complain, although the input is valid according to the constraints specified in the link your provide.
==298664==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffce142a650 at pc 0x55697440f74d bp 0x7ffce14209c0 sp 0x7ffce14209b8
WRITE of size 4 at 0x7ffce142a650 thread T0
#0 0x55697440f74c in maxum(int*, int) (/tmp/a.out+0x174c)
#1 0x55697440f26c in main (/tmp/a.out+0x126c)
#2 0x7fc97926acc9 in __libc_start_main ../csu/libc-start.c:308
#3 0x55697440f3a9 in _start (/tmp/a.out+0x13a9)
[rest of asan output omitted]
I tryed to run the following code in my cygwin
#include<iostream>
#include<cstdio>
using namespace std;
const int NR=2005;
int n,m;
bool arr[NR][NR];
int mx_jx(int x){
int up[NR][NR],lf[NR][NR],rt[NR][NR];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
up[i][j]=1,lf[i][j]=rt[i][j]=j;
for(int i=1;i<=n;i++)
for(int j=2;j<=m;j++)
if(arr[i][j-1]==x)lf[i][j]=lf[i][j-1];
for(int i=1;i<=n;i++)
for(int j=m-1;j>=1;j--)
if(arr[i][j+1]==x)rt[i][j]=rt[i][j+1];
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(arr[i][j]!=x)continue;
if(i>1 && arr[i-1][j]==x){
up[i][j]=arr[i][j-1]+1;
lf[i][j]=max(lf[i][j],lf[i-1][j]);
rt[i][j]=min(rt[i][j],rt[i-1][j]);
}
ans=max(ans,(rt[i][j]-lf[i][j]+1)*up[i][j]);
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int tmp;
scanf("%d",&tmp);
arr[i][j]=(int)tmp;
if((i+j)&1)arr[i][j]=!arr[i][j];
}
printf("%d",max(mx_jx(0),mx_jx(1)));
return 0;
}
It passed the compile(0 warning,0 error), but when I tried to run it with the following input
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
It says "Command terminated"
these code could run correctly on other platform, how can I solve this problem on cygwin? thanks a lot
While the answer from user3684240 is valid and it is definitely an issue with your code, more likely you have Stack Overflow due to allocating numerous huge arrays on stack and in global memory area.
You should use std::vector<std::vector<int> instead of plain C arrays.
std::vector<std::vector<int>> up(NR, std::vector<int>(NR, 0));
std::vector<std::vector<int>> lf(NR, std::vector<int>(NR, 0));
std::vector<std::vector<int>> rt(NR, std::vector<int>(NR, 0));
It is not very well optimized, but it's simplest solution I can provide.
For that bool array though, std::vector might behave... strange. I cannot give 100% guarantee that it will work if you simply substitute bool[][] with std::vector<std::vector<bool>> without testing it properly, because std::vector<bool> is optimized for memory and it has certain quirks that one should be aware of when using it.
You can try and see if that array of bools in global memory works (after changing arrays in mx_jx to vectors), maybe it does and you don't have to change it. If it doesn't, you can try to change to vector of vectors, then it should work.
The mistake is in that line:
scanf("%d", &arr[i][j]);
%d reads ints, but your array is of type bool. This leads to a memory error.
An easy way to fix it would be:
int read_value;
scanf("%d", &read_value);
arr[i][j] = read_value;
As an additional hint: If you enable compiler warnings (-Wall -Wextra -pedantic), the compiler will tell you about those kinds of mistakes.
I am using cudaMemGetInfo in order to get the vram currently used by the system.
extern __host__ cudaError_t CUDARTAPI cudaMemGetInfo(size_t *free, size_t *total);
And I am having two problems :
the main is that the free value returned is only right when the graphic device has almost no memory free for allocation. Otherwise it remains at about 20% memory used even when GPU-Z clearly states that about 80 % is used. And when I reach 95% memory used cudaMemGetInfo suddenly returns a good value. Note that the total memory is always correct.
the second problem is that as soon as I use the function, video memory is allocated. At least 40mbytes but it can reach 400 on some graphic devices.
My code :
#include <cuda_runtime.h>
size_t Profiler::GetGraphicDeviceVRamUsage(int _NumGPU)
{
cudaSetDevice(_NumGPU);
size_t l_free = 0;
size_t l_Total = 0;
cudaError_t error_id = cudaMemGetInfo(&l_free, &l_Total);
return (l_Total - l_free);
}
I tried with 5 different nvidia graphic devices. The problems are always the same.
Any idea ?
On your first point, I cannot reproduce this. If I expand your code into a complete example:
#include <iostream>
size_t GetGraphicDeviceVRamUsage(int _NumGPU)
{
cudaSetDevice(_NumGPU);
size_t l_free = 0;
size_t l_Total = 0;
cudaError_t error_id = cudaMemGetInfo(&l_free, &l_Total);
return (l_Total - l_free);
}
int main()
{
const size_t sz = 1 << 20;
for(int i=0; i<20; i++) {
size_t before = GetGraphicDeviceVRamUsage(0);
char *p;
cudaMalloc((void **)&p, sz);
size_t after = GetGraphicDeviceVRamUsage(0);
std::cout << i << " " << before << "->" << after << std::endl;
}
return cudaDeviceReset();
}
I get this on a linux machine:
$ ./meminfo
0 82055168->83103744
1 83103744->84152320
2 84152320->85200896
3 85200896->86249472
4 86249472->87298048
5 87298048->88346624
6 88346624->89395200
7 89395200->90443776
8 90443776->91492352
9 91492352->92540928
10 92540928->93589504
11 93589504->94638080
12 94638080->95686656
13 95686656->96735232
14 96735232->97783808
15 97783808->98832384
16 98832384->99880960
17 99880960->100929536
18 100929536->101978112
19 101978112->103026688
and I get this on a Windows WDDM machine:
>meminfo
0 64126976->65175552
1 65175552->66224128
2 66224128->67272704
3 67272704->68321280
4 68321280->69369856
5 69369856->70418432
6 70418432->71467008
7 71467008->72515584
8 72515584->73564160
9 73564160->74612736
10 74612736->75661312
11 75661312->76709888
12 76709888->77758464
13 77758464->78807040
14 78807040->79855616
15 79855616->80904192
16 80904192->81952768
17 81952768->83001344
18 83001344->84049920
19 84049920->85098496
Both seem consistent to me.
On your second point: cudaSetDevice establishes a CUDA context on the device number which you pass to it, if no context already exists. Establishing a CUDA context will reserve memory for the runtime components required to run CUDA code. So it is completely normal that calling the function will consume memory if it is the first CUDA API containing function you call.
I have been searching all over and cannot find anything like this. Now, I won't bore you with my whole program. It's incredibly long. But, here's your basic overview:
int main()
{
int i=0;
int h=5;
cout << "h(IS) = " << h << endl;
cout << "testing comment.";
while(i < 10)
{
cout << "I'm in the loop!";
i++;
}
return 0;
}
Looks great, right? Okay, so here's the problem. I run it, and I get a segmentation fault. The weirdest part is where I'm getting it. That testing comment doesn't even print. Oh, and if I comment out all the lines before the loop, I still get the fault.
So, here's my output, so you understand:
h(IS) = 5
Segmentation fault
I am completely, and utterly, perplexed. In my program, h calls a function - but commenting out both the line that prints h and the function call have no effect, in fact, all it does is give the segmentation fault where the line ABOVE the printing h line used to be.
What is causing this fault? Anything I can do to test where it's coming from?
Keep your answers simple please, I'm only a beginner compared to most people here :)
Note: I can provide my full code upon request, but it's 600 lines long.
EDIT: I have pasted the real code here: http://pastebin.com/FGNbQ2Ka
Forgive the weird comments all over the place - and the arrays. It's a school assignment and we have to use them, not pointers. The goal is to print out solutions to the 15-Puzzle. And it's 1 AM, so I'm not going to fix my annoyed comments throughout the thing.
I most recently got irritated and commented out the whole first printing just because I thought it was something in there...but no...it's not. I still get the fault. Just with nothing printed.
For those interested, my input information is 0 6 2 4 1 10 3 7 5 9 14 8 13 15 11 12
THANK YOU SO MUCH, EVERYONE WHO'S HELPING! :)
You slip over array boundaries, causing the corruption:
for (i=0; i<=4; i++)
{
for (j=0; j<=4; j++)
{
if (cur[i][j] == 0)
{
row = i;
col = j;
}
}
}
Your i and j indices must not reach 4.
valgrind is a great tool for debugging memory access problems. It's very easy to use on Linux. Just install G++ and valgrind, and then run (without the $ signs):
$ g++ -g -o prog prog.cpp
$ valgrind ./prog
It will print very detailed error messages about memory access problems, with source code line numbers. If those still don't make sense to you, please post the full source code (prog.cpp) and the full output of valgrind.
I've run valgrind for you, its output is here: http://pastebin.com/J13dSCjw
It seems that you use some values which you don't initialize:
==21408== Conditional jump or move depends on uninitialised value(s)
==21408== at 0x8048E9E: main (prog.cpp:61)
...
==21408== Conditional jump or move depends on uninitialised value(s)
==21408== at 0x804A809: zero(int (*) [4], int (*) [4], int*, int, int, int, int, int, int) (prog.cpp:410)
==21408== by 0x804A609: lowest(int (*) [4], int (*) [4], int, int, int, int, int, int) (prog.cpp:354)
==21408== by 0x804932C: main (prog.cpp:125)
...
To fix these problems, add code which initializes the variables depicted in the error lines above (e.g. line 61, 410), then recompile, and rerun with valgrind again, until all errors disappear.
If your program behaves weirdly even after fixing all problems reported by valgrind, please let us know.
Lines 57 - 67:
for (i=0; i<=4; i++)
{
for (j=0; j<=4; j++)
{
if (cur[i][j] == 0)
{
row = i;
col = j;
}
}
}
at least one of your errors is in this code, cur is declared int cur[4][4]; this means then when j==4 (and when i==4) you are not within the bounds of your array (well you are within the memory for some of them, but not all) valid values will be 0 - 3.
I'm writing a shell in c++, and I need a constructor for my CommandLine class that parses a command from the istream, and then uses the calloc() and free() system calls to dynamically create argc and argv variables. I don't get how to use the system calls to do this, and no tutorial has helped.
Here's an example very similar to what you're asking for. I found it here: http://www.cplusplus.com/reference/clibrary/cstdlib/calloc
function calloc
void * calloc ( size_t num, size_t size );
Allocate space for array in memory Allocates a block of memory for an
array of num elements, each of them size bytes long, and initializes
all its bits to zero.
The effective result is the allocation of an zero-initialized memory
block of (num * size) bytes.
Parameters
num
Number of elements to be allocated. size
Size of elements.
Return Value A pointer to the memory block allocated by the function.
The type of this pointer is always void*, which can be cast to the
desired type of data pointer in order to be dereferenceable. If the
function failed to allocate the requested block of memory, a NULL
pointer is returned.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* calloc example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i,n;
int * pData;
printf ("Amount of numbers to be entered: ");
scanf ("%d",&i);
pData = (int*) calloc (i,sizeof(int));
if (pData==NULL) exit (1);
for (n=0;n<i;n++)
{
printf ("Enter number #%d: ",n);
scanf ("%d",&pData[n]);
}
printf ("You have entered: ");
for (n=0;n<i;n++) printf ("%d ",pData[n]);
free (pData);
return 0;
}