Wrong use of memset? - c++

Can someone please explain what is wrong here:
class test
{
public:
char char_arr[100];
};
int main()
{
test **tq = (test**)calloc(10, sizeof(test*));
for(unsigned int i = 0; i < 10; i++)
tq[i] = (test*)calloc(10, sizeof(test));
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
return 0;
}
The code above produces random crashes. The errors are: "memory could not be written", "memory could not be read", "stack is corrupted"

test **tq = (test**)calloc(10, sizeof(test*));
...
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
When you allocate tq, you ask for 10 * sizeof(test*) bytes. But when you call memset, you ask it to set sizeof(tq[0][0]*100) bytes. You are definitely writing to more bytes then you allocated. Perhaps you meant:
for(unsigned int i = 0; i < 10; i++)
memset(tq[i], 0, 10 * sizeof(test));
This makes sense because:
tq[i] = (test*)calloc(10, sizeof(test));
When you allocated tq[i], you allocated 10 * sizeof(test) bytes.

You are confusing this for a 2D array:
char x[10][10];
This is a 2D array, which holds 100 contiguous chars.
But you have allocated a bunch of pointers, then pointed them to separate arrays of 10 chars each. The result is not contiguous; you cannot access it in the way you have.

Related

Thread 1: EXC_BAD_ACCESS (code 1) error

When I run this short program, I generate the error "Thread 1: EXC_BAD_ACCESS (code 1)". Can anyone help me determine the cause of the problem?
//populates matrix with rand nums
void popMat(int x[][4096]){
for(int i = 0; i < 4096; i++){
for(int j = 0; j < 4096; j++){
x[i][j] = rand() % 100;
}
}
return;
}
int main(int argc, char * argv[]) {
int mat1 [4096][4096];
int mat2 [4096][4096];
popMat(mat1);
popMat(mat2);
for(int i = 0; i < 4096; i++){
for(int h = 0; h < 4096; h++){
printf("%d, %d\n", i, h);
}
}
return 0;
}
Assuming 4 bytes integer, int mat1 [4096][4096]; requires 64MB of memory. Two such arrays require 128 MB of memories. On most systems stack memory, where local variables are created, is not capable of storing such large memory and you are getting a stack overflow.
One easy solution is to move the array is global scope(using global is not much recommended). Another solution is to allocate these arrays dynamically with malloc or new. Another solution is to use std::vector instead of statically allocated C arrays.
PS:
Do not forget to free memory if you decide to allocate them dynamically.
Even after you fix this issue you will see that rand() is always generating same values as srand() is not called.

C++ : EXC_BAD_ACCESS at basic for loop

int main(int argc, const char * argv[]) {
int N,M;
std::cin >> N;
std::cin >> M;
bool member[N];
for (int i= 0; i < N ; i++) {
member[i] = false;
}
int test[M][N];
int testSize[M];
/*//std::fill_n(testSize, M, 0);
for (int i = 0; i < M; i++) {
std::fill_n(test[M], N, -1);
}*/
for (int i = 0; i < M; i++) {
for (int j = 0; j < N ; j++) {
test[i][j] = -1;
}
testSize[i] = 0;
}
}
This is my c++ code above, that is simple code, isn't it?
But When the program got M as 100000 and N as 1000, there is EXC_BAD_ACCESS at second for loop.
I do not know why it is happening.
When smalle size data is put into, there is no error, but This case made it an error.
I'm solving an algorithm problem and confronting unknowing error.
Is there any point to fix at my program?
As you see my code, what I want is to initialize the array test and testSize to the same value; -1 and 0.
int test[M][N]; allocates an array of M*N elements on the stack. When M == 100000 and N==1000 it is an array of 100 million elements. int is usually at least 4 bytes, so you are trying to allocate 400MB array on a stack, which won't fit with default (or probably any at all) linker settings.
What you can do is to allocate that much memory on heap using malloc or new[]. You can also use 3rd-party classes for operating matrices that will do it for you.

Why is the array size becoming so large?

I've been battling with figuring out how to pass a 2D array to a function and I think I've figured it out. My problem now though is for some reason this array (see below) is growing from 25 to 100 and I can't figure out why. I can't pinpoint where it's going haywire.
#include <iostream>
void testFunc(int (&n)[5][5]) {
n[0][0] = 5;
}
int main() {
int arr3[5][5];
// The array is initialized here with all values equaling 8.
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
arr3[i][j] = 8;
}
}
testFunc(arr3); // Function is called here changing [0][0] to the value 5.
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
std::cout << arr3[i][j] << ' ';
}
std::cout << '\n' << std::endl;
}
std::cout << sizeof(arr3) << std::endl;
return 0;
}
When I try to write the for-loop with i < sizeof(arr3) I get a size of 100. Not sure why. Where is it getting that value?
Your array size is 5*5 = 25, and int takes 4 bytes. so it becomes 100.
sizeofis not the number of elements. It's the size of the object in chars, that is, in bytes for most modern systems.
Your system has 32-bit (4 char/bytes) ints. Which gives you 5*5*4 = 100.
The size of data is also depend on size of CPU registers. In 32 bit machine the size of int is 4. However in earlier 16 bit machines the size of int is 2.

Two-dimensional array initialization

CASE1:
int nrows=5;
int ncols=10;
int **rowptr;
rowptr=new int*;
for(int rows=0;rows<nrows;rows++) {
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
CASE2:
int nrows=5;
int ncols=10;
int **rowptr;
for(int rows=0;rows<nrows;rows++) {
rowptr=new int*;
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
I am able to insert and print values using both ways. What is the difference in initializations?
What is the difference?
#1 just allocates memory enough to hold a integer pointer and not an array of integer pointers.
#2 Causes a memory leak by just overwritting the memory allocation of the previous iteration.
I am able to insert and print values using both the ways
Memory leaks and Undefined behaviors may not produce immediate observale erroneous results in your program but they sure are good cases of the Murphy's Law.
The correct way to do this is:
int nrows = 5;
int ncols = 10;
//Allocate enough memory for an array of integer pointers
int **rowptr = new int*[nrows];
//loop through the array and create the second dimension
for (int i = 0;i < nrows;i++)
rowptr[i] = new int[ncols];
You have a memory leak in both cases.
The proper way to initialize such a "2d" array is
int** arr = new int*[nrows];
for (int i = 0; i < nrows; i++)
arr[i] = new int[ncols];
Note however, that it isn't a 2d array as defined by C/C++. It may not, and probably will not, be consecutive in memory. Also, the assembly code for accessing members is different.
In your case, the accessing by indexing is equivalent to *(*(arr+i)+j)
And in the case of a 2d array it's *(arr + N_COLS*i + j) when N_COLS is a compile time constant.
If you want a true 2d array you should do something like this:
int (*arr)[N_COLS] = (int(*)[N_COLS])(new int[N_ROWS * N_COLS])
You'd better use 1d array to manage 2d array
int **x = new int*[nrows];
x[0] = new int[nrows*ncols];
for (int i = 1; i < nrows; i++)
x[i] = x[i-1] + ncols;
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++)
x[i][j] = 0;
delete [] x[0];
delete [] x;

fwrite, fread - problems with fread

I have following code:
int main()
{
char* pedal[20];
char* pedal2[20];
for (int i = 0; i < 20; i++)
{
pedal[i] = "Pedal";
}
FILE* plik;
plik = fopen("teraz.txt","wb");
for (int i = 0; i < 20; i++)
{
fwrite(pedal[i],strlen(pedal[i]),1,plik);
}
system("pause");
fclose(plik);
plik = fopen("teraz.txt","rb");
for (int i = 0; i < 20; i++)
{
fread(pedal2[i],5,1,plik); //I know for now that every element has 5 bytes
}
for (int i = 0; i < 20; i++)
{
std::cout << pedal2[i] << std::endl;
}
fclose(plik);
system("pause");
return 0;
}
It's crashing at reading and second question let's assume that I have structure where I keep like integers, floats and also char* array and how can I easly write whole structure to the file? Normal fwrite with sizeof structure is not working
Your problem that you didn't allocate buffer for reading. In fact line
fread(pedal2[i],5,1,plik)
reads to unknown place. You need allocate memory (in your case it is 5 + 1 bytes for zero terminated string).
pedal2[i] = malloc(5+1);
fread(pedal2[i],5,1,plik)
Don't forget to release it after usage.
You can't read into pedal2 without first having allocated space for it.
You need something like this:
for (int i = 0; i < 20; ++i) {
pedal[i] = malloc(100); //allocate some space
}
Your first question seem to have already been answered by Simone & Dewfy.
For your second question about how to write structure values into the file, you will have to write member by member.
Please check fprintf. You can probably use it for writing different data types.