This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 6 years ago.
I would like to understand why this piece of code will not crash :
#include<studio.h>
#include<string.h>
main()
{
char *a;
a=(char *)malloc(1);
strcpy(a, "example");
}
I though we are writing to memory that is not the processes' since we allocate only 1 byte for the char * and we write more than that.
Can somebody please explain?
Thanks in advance.
Allocate enough space for the string.
#include <stdio.h>
#include <string.h>
int main()
{
char * a;
a = (char *)malloc(32);
strcpy(a, "example");
free(a); // don't forget to free
}
Explanation:
You allocated 1 byte you copied 7+1 (example + '\0').
You tried to access memory that was not allocated.
Read articles about buffer overflow.
Important:
If you are not aware of the input size (now we know "example" is 7+1 bytes)
you should use strncpy to specify the maximum number of bytes that can be copied.
There is a function strdup that duplicates the string. Same as allocation + strcpy.
Your allocator may allocate small chunks of fixed size for requests below certain threshold. I wouldn't be surprised you've got 8 bytes back, so strcpy works without crash
Related
This question already has answers here:
What is the size of a pointer? [duplicate]
(8 answers)
Closed 6 months ago.
I want to add a string after the struct in memory.
How to check that i dynamically allocated right amount of bytes?
Example:
const wchar_t* add_str = L"test string";
struct test_{
wchar_t* name;
size_t namelen;
} test;
void* ptest_void = malloc(sizeof(test) + wcslen(add_str)*sizeof(wchar_t));
// i cant dereference void*, hence, cant check sizeof(*ptest_void)
// then i try to get sizeof of a ptr which was cast to (test_*):
test_* ptest = (test_*)ptest_void;
size_t ptest_sz = sizeof(*ptest);
// ptest_sz has the size of _test struct, but without size of add_str...
free(ptest_void);
sizeof(ptest) doesn't tell you how much allocated memory ptest points to. It tells you the size in bytes of the variable ptest, most likely either 4 or 8 depending on your system.
There's also no standard way to check "how big" an allocated block of memory it. You're expected to keep track of that yourself.
If a call to malloc does not return NULL, that means the call was successful, and you can access as many bytes as you told it to allocate.
This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 3 years ago.
Program with large global array:
int ar[2000000];
int main()
{
}
Program with large local array:
int main()
{
int ar[2000000];
}
When I declare an array with large size in the main function, the program crashes with "SIGSEGV (Segmentation fault)".
However, when I declare it as global, everything works fine. Why is that?
Declaring the array globally causes the compiler to include the space for the array in the data section of the compiled binary. In this case you have increased the binary size by 8 MB (2000000 * 4 bytes per int). However, this does mean that the memory is available at all times and does not need to be allocated on the stack or heap.
EDIT: #Blue Moon rightly points out that an uninitialized array will most likely be allocated in the bss data segment and may, in fact, take up no additional disk space. An initialized array will be allocated statically.
When you declare an array that large in your program you have probably exceeded the stack size of the program (and ironically caused a stack overflow).
A better way to allocate a large array dynamically is to use a pointer and allocate the memory on the heap like this:
using namespace std;
int main() {
int *ar;
ar = malloc(2000000 * sizeof(int));
if (ar != null) {
// Do something
free(ar);
}
return 0;
}
A good tutorial on the Memory Layout of C Programs can be found here.
This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 3 years ago.
Program with large global array:
int ar[2000000];
int main()
{
}
Program with large local array:
int main()
{
int ar[2000000];
}
When I declare an array with large size in the main function, the program crashes with "SIGSEGV (Segmentation fault)".
However, when I declare it as global, everything works fine. Why is that?
Declaring the array globally causes the compiler to include the space for the array in the data section of the compiled binary. In this case you have increased the binary size by 8 MB (2000000 * 4 bytes per int). However, this does mean that the memory is available at all times and does not need to be allocated on the stack or heap.
EDIT: #Blue Moon rightly points out that an uninitialized array will most likely be allocated in the bss data segment and may, in fact, take up no additional disk space. An initialized array will be allocated statically.
When you declare an array that large in your program you have probably exceeded the stack size of the program (and ironically caused a stack overflow).
A better way to allocate a large array dynamically is to use a pointer and allocate the memory on the heap like this:
using namespace std;
int main() {
int *ar;
ar = malloc(2000000 * sizeof(int));
if (ar != null) {
// Do something
free(ar);
}
return 0;
}
A good tutorial on the Memory Layout of C Programs can be found here.
This question already has answers here:
How could it get more memory than I wanted?(C++) [duplicate]
(2 answers)
Closed 8 years ago.
I was experimenting with the pointers. I initially, created a pointer to a character and allocated a size of 2 bytes the pointer. Then I ran loop till 1000 assigning some values. When I try to print the String it gives me a whole set values that have been assigned.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char *a = (char *)malloc(2);
for (int i=0;i<10;i++)
a[i]='a';
cout<<a<<"\t"<<strlen(a)<<"\n";
return 0;
}
The output will be as follows
aaaaaaaaaa 10
I ran the same code in both C and C++. They are giving me the same result.
As of a first thought, since I used the pointers, a[3] mean *(&a + 3): which would explain why I am able to assign a value to that location. But, even when I allocated only two bytes of memory to String, Why is my string length being varied? Why is that the compiler behaving in a different manner? What goes behind the screen?
OS: OS X 10.10.0
compiler: gcc || g++
Architecture: 64-bit Architecture
Edit1: It is not about the seg fault.
Edit2: If it is because the strlen reads until it encounters a null terminator. I haven't declared it at the end of the string.
This code is have problem in memory usage. Only 2 bytes of memory is allocated but 10 byes is used. This will cause memory corruption. Then the behavior is undefined.
for (int i=0;i<1 /*10*/;i++)
In your case the max i value can be 1 not 10. The remaining 1 bye is for \0 character.
This question already has answers here:
Quick strlen question
(9 answers)
Closed 9 years ago.
I am writing simple function for merging two C-strings. While trying to dynamically alocate new chunk of memory i found out that :
char * out = new char[size];
std::cout << strlen(out) <<std::endl;
Returns 16 when size is 4 and 40 when size is 22 and so on.
Does anyone have an idea why it acts like that and how to allocate memory for c-string with certain number of chars?
The allocated memory is not initialized. strlen() just keeps charging through memory until it encounters a null character ('\0'). Since you have not initialized the memory pointed to by out, the contents of this memory are undefined, and therefore so is the behavior of strlen().
strlen() does not measure the size of an allocation, so your interpretation that new is allocating too much memory is incorrect simply because the tool you are using to measure the size of the allocation doesn't do that at all.
In your case, strlen() is reading beyond the boundary of this allocation. In this circumstance, the result could be a "wrong" value (as you see here) or your program could simply crash.
Using new to allocate memory does not initialize the memory:
char * out = new char[size];
// Add this code to initialize out
memset(out,'A',size-1);
out[size-1]='\0';
std::cout << strlen(out) <<std::endl;