Heap data transfer

Fortunately, I found many useful answers here, reading other questions, but this time I am completely helpless, so I myself must ask the question:

I am trying to create a program that applies convolution to a series of data. For convolution kernels (= arrays of certain numbers) that have different lengths.

I implement this using float** and inserting values ​​into double-dereferenced variables. The number of arrays is fixed, the length of each array is missing, so the "subarrays" are allocated using new - in the CreateKernels function after if .

This function then returns float** along with another pointer associated as a structure with the main one.

Now the problem is: I looked at the dereferenced values ​​of my kernel pointers using a debug clock. Everything worked fine, and all numbers were calculated after the CreateKernels (i.e., they CreateKernels memory from the main ). But after the next command in main my numbers are completely screwed up. If I try to use the data in the following code, I get segfault.

So, what is my current reasoning: Since I use new to create variables, they should be on the heap and should remain there until I free[] is the xmdash variable; in any case, they should not be limited to the CreateKernels area. Assigning pointers to the kernel structure and returning them may be strange for some of you, but it works. So, what really ruins my data is the next command after CreatKernels . Initializing int instead of creating fstream will not ruin my numbers. But why?

Is this a management error for my OS? Or is this a stupid programming error? I run Ubuntu 12.04-64bit and used both Code::Blocks and g++ to compile (all default settings), and both executables give me segfault.

I would really appreciate any hint or experience in this issue!

This is the corresponding code:

 #include <string> #include <stdlib.h> #include <iostream> #include <fstream> #include <iomanip> #define HW width/2 #define width1 4 // kernel width-1 (without peak) using namespace std; struct kernel_S { const float ** ppkernel; const float * pnorm; }; void BaseKernel(const int & width, float * base) // function that fills up an 1d-array of floats at the location of base { for(int i=0; i<=HW-1; i++) // fill left half as triangle { base[i] = i+1; } base[HW] = HW+1; // add peak value for(int i=HW+1; i<=width; i++) // fill right half as decreasing triangle { base[i] = width-i+1; } } kernel_S CreateKernels(const int &width) // function that creates an array of arrays (of variable length) { float base_kernel[width+1]; // create a full width kernel as basis BaseKernel(width, base_kernel); float * kernel[width+1]; // array of pointers, at each destination of a pointer a kernels is stored float norm[width+1]; // norm of kernel for(int j=0; j<=width; j++) // fill up those individual kernels { norm[j] = 0; if(j<=HW) // left side up to peak { kernel[j] = new float[HW+j+1]; // allocate mem to a new array to store a sub-kernel in for(int i=0; i<=HW+j; i++) { *(kernel[j]+i) = base_kernel[HW-j+i]; //use values from base kernel norm[j] += base_kernel[HW-j+i]; // update norm } } else if(j>=HW+1) { kernel[j] = new float[HW+width-j+2]; for(int i=0; i<=HW+width-j; i++) { *(kernel[j]+i) = base_kernel[i]; norm[j] += base_kernel[i]; // update norm } } } kernel_S result; // create the kernel structure to be returned result.ppkernel = (const float **) kernel; // set the address in the structure to the address of the generated arrays result.pnorm = (const float *) norm; // do the same for the norm return result; } int main() { kernel_S kernels = CreateKernels(width1); // Create struct of pointers to kernel data ifstream name_list(FILEPATH"name_list.txt", ios::in);// THIS MESSES UP THE KERNEL DATA // some code that would like to use kernels return 0; } 
+4
source share
1 answer

Cm.

How to use arrays in C ++?

You are returning pointers to local stack data (kernel and norm). You should highlight dynamically:

 float ** kernel = new float*[width+1]; // array of pointers, at each destination of a pointer a kernels is stored float *norm = new float[width+1]; // norm of kernel 

Remember to delete with delete [].

However, I suggest using std :: vector or std :: array instead

 #include <string> #include <stdlib.h> #include <iostream> #include <fstream> #include <iomanip> #include <vector> #define HW width/2 #define width1 4 // kernel width-1 (without peak) using namespace std; typedef std::vector<float> floatV; typedef std::vector<floatV> floatVV; struct kernel_S { floatVV kernel; floatV norm; }; floatV BaseKernel(int width) // function that fills up an 1d-array of floats at the location of base { floatV base; base.resize(width + 1); for(int i=0; i<=HW-1; i++) // fill left half as triangle { base[i] = i+1; } base[HW] = HW+1; // add peak value for(int i=HW+1; i<=width; i++) // fill right half as decreasing triangle { base[i] = width-i+1; } return base; } kernel_S CreateKernels(const int &width) // function that creates an array of arrays (of variable length) { const floatV base_kernel = BaseKernel(width); // create a full width kernel as basis kernel_S result; // create the kernel structure to be returned result.kernel.resize(base_kernel.size()); result.norm.resize(base_kernel.size()); for(int j=0; j<=width; j++) // fill up those individual kernels { result.norm[j] = 0; if(j<=HW) // left side up to peak { result.kernel[j].resize(HW+j+1); // allocate mem to a new array to store a sub-kernel in for(int i=0; i<=HW+j; i++) { result.kernel[j][i] = base_kernel[HW-j+i]; // use values from base kernel result.norm[j] += base_kernel[HW-j+i]; // update norm } } else if(j>=HW+1) { result.kernel[j].resize(HW+width-j+2); for(int i=0; i<=HW+width-j; i++) { result.kernel[j][i] = base_kernel[i]; result.norm[j] += base_kernel[i]; // update norm } } } return result; } int main() { kernel_S kernels = CreateKernels(width1); // Create struct of pointers to kernel data ifstream name_list("name_list.txt", ios::in); // some code that would like to use kernels return 0; } 

Note If you want kernel and norm be const inside the resulting structure, just create the whole const structure:

  const kernel_S kernels = CreateKernels(width1); 
+3
source

Source: https://habr.com/ru/post/1446648/


All Articles