It seems that following code is leaking memory. I checked the JVM memory utilization and it is not freeing up memory after subsequent calls. When I just run the Java as standalone it works fine for multiple calls and keeps deallocating memory just fine.
I would really appreciate any help.
jobjectArray my_obj = (jobjectArray) env->CallObjectMethod(cls, mid, qstr, pstr);
length = env->GetArrayLength(my_obj);
//printf("\nArray Length = %d \n", length);
char result[256];
const char *cstr;
int numberOfCharsInThisRow = 0;
array1 = (char **)malloc(length * sizeof(char *));
/*Check if pointer is null, if not then free its memory first*/
for(int i=0; i< length ; i++){
cstr = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(my_obj,i), 0);
numberOfCharsInThisRow = std::strlen(cstr)+1;
*(array1+i)=(char *)malloc(numberOfCharsInThisRow * sizeof(char));
std::strcpy(result, cstr);
std::strcpy(*(array1+i),result);
env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(my_obj,i), cstr);
}
env->DeleteLocalRef(my_obj);
}
//printf("\n\nDestroy JVM\n\n");
//jvm->DestroyJavaVM();
}
void libdeallocatememory(char **array1,int length)
{
//printf("Free Array memory \n");
for (int j=0 ;j <length ;j ++)
{
free(array1+j);
}
free(array1);
}
You should free the array1 pointers once you are done with them. What does this function do in reality? From the functionality I understood, you are copying from the java to a c pointer. What happens next? By calling ReleaseStringUTF, you are notifying the JVM that it isnt being used in native and so can be GCed when required
Think I have found the problem. Releasing Code should be something like
for (int j=0 ;j<length; j++ )
{
free(array1[j]);
}
free(array1);
The initial allocation should be array1 = (char **)malloc(length * sizeof(int *));
The difference is int* instead of char*. This is because this array is just an array of pointers. Pointer size is int. The next level is in the loop where you allocate memory for your strings. It should be array1[i] = (char *)malloc(numberOfCharsInThisRow * sizeof(char));
That means initially you allocated an array of pointers. Now for each element of that arary, you are allocating the memory to hold its own string. I think even *(array1+i) will work, but I find this more easy to read. So when you free, first you free the individual array elements you allocated, and then the entire array which you allocated initially. As an example, take a look at your current deallocate function. There is no difference between the free when j=0 and the last free. I am surprised you are not getting any crashes.
Take a look at http://c-faq.com/~scs/cclass/int/sx9b.html
Also try the following jstring myString =env->GetObjectArrayElement(my_obj,i); Use myString to get the UTFChars, Then call env->ReleaseStringUTFChars(mystring, cstr)
Related
The code below ask the user to input 10 pairs of artist and titles which can be up to 30 characters long. Everything seems to work fine with allocating the space and printing the data back out. The problem only occurs when I try to free the memory at then end and then only if one of the elements is 4 or more characters long. I suspect I am not allocating the memory correctly but I just can't see it.
// Songs.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
// Experimenting with pointers, structures and dynamic allocation of memory
//
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream>
#include <stdio.h>
struct songInfo
{
char* pArtist; // char pointer for Artist data
char* pTitle; // char pointer for Title data
};
// function prototype declarations
void getSongInfo(struct songInfo *songData, char *Artist, char *Title);
void printSongInfo(songInfo *songData);
int main()
{
struct songInfo songData[10]; // setup array of 10 elements of the structure SongInfo
char sArtist[31];
char sTitle[31];
// prompt user for the artist and title 10 times once for each array element
for (int i = 0; i < 10; i++) {
printf("Artist %i: ", i + 1);
fgets(sArtist, 31, stdin);
strtok(sArtist, "\n"); // trim out return character
printf("Title %i: ", i + 1);
fgets(sTitle, 31, stdin);
strtok(sTitle, "\n"); // trim out return character
getSongInfo(&songData[i], sArtist, sTitle); // allocates the memory and stores the data into the pointer location
}
printSongInfo(songData); // printout the song data stored in the array
// free up the allocated memory space
for (int i = 0; i < 10; ++i) {
free(songData[i].pArtist);
free(songData[i].pTitle);
}
return 0;
}
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(sizeof(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(sizeof(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
void printSongInfo(songInfo *songData) {
printf("\n%-35s %-35s\n", "Artist", "Title");
printf("%-35s %-35s\n", "-----------------------------------", "-----------------------------------");
for (int i = 0; i < 10; i++) { // iterate through the array of elements
printf("%-35s %-35s\n", songData[i].pArtist, songData[i].pTitle);
}
}
It's not free() call that is invalid, it's malloc.
If you'd print out sizeof(Artist) + 1, you'd likely get either 5 or 9 (depending on your computer architecture). And the same for Title. You check the size of pointer on your machine, which is constant, not the size of array you received.
Undefined Behvaiour means your code may do anything, including "working for now, but will break later at a correct place". You invoke UB by calling strcpy, which tries to copy data into buffer too short to contain the whole string.
You have to pass the size of array to function or calculate it using strlen inside function (and pray that the string is actually null-terminated).
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(strlen(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(strlen(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
Use std::char_traits::length or strlen. Instead of length of the array, sizeof(Artist) gives you how many bytes a char * pointer occupies.
songData->pArtist =
(char*)malloc(std::char_traits<char>::length(Artist) +
1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle =
(char*)malloc(std::char_traits<char>::length(Title) +
1); // Allocate enough memory to hold the string and the null terminator
Just a side note: using std::string and smart pointers such as std::unique_ptr and std::shared_ptr would save you lots of troubles dealing with memory issues. Overall, using modern c++ will help you write safer code more efficiently.
I get this error :
"crt detected that the application wrote to memory after end of heap
buffer"
this program should write every second sign...
char x = 1;
while ( x != 0) {
char *ptr(0);
ptr = new char;
fgets(ptr, 100001, stdin);
for (char i = 0; i < sizeof(ptr); i++) {
cout << *(ptr + i);
i++;
}
cout << endl;
delete ptr;
ptr = 0;
}
ptr = new char; allocates exactly one byte for the pointer. Than fgets(ptr, 100001, stdin); attempts to read up to 100001 characters into it, obviously well beyond it's allocated boundary.
The immediate solution would be to make sure you allocate the buffer with adequate size using array form of new, i.e. ptr = new char[100001];. This, in turn, will lead to changing the delete into it's array form as well: delete[] ptr
Also, keep in mind that sizeof(ptr) will give you the size of the pointer (4 or 8 bytes on most platforms). You would want to use strlen or similar to find out when the string ends.
All suggestions above should be taken in light of the learning exercise. In real life, you should not do this, and instead use std::string and modern ways of string-oriented reading. (std::getline would be the most readily available).
sizeof returns size in bytes of the object representation of type. https://en.cppreference.com/w/cpp/language/sizeof
One other point major point to note is that ptr = new char will only allocate exactly one byte from the heap. But in your code you are trying to read 100001 bytes and obviously this is beyond the accessible memory range of that pointer.
you can modify the error as ptr = new char[100001]; When you do this, there is another change that you must do in order to avoid memory leaks.
That being, delete[] ptr. Because you have allocated 100001 adjacent bytes, you have to de-allocate them all.
How to copy a matrix into where a pointer points to?
I am new in c++. I tried a lot but I could not find any solution.
here is my code:
float *output = new float[HighRange];
output = new float[10 * 10];
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
output[j]=input[i][j]; ---> I have error in this line
Thanks in advance
There are several ways to arrange the elements of input in output. Here is one way:
output[i*10 + j] = input[i][j]
Aside from NPEs suggestion, you have a memory leak here:
float *output = new float[HighRange]; // allocate contiguous block HighRange * sizeof(float) bytes
output = new float[10 * 10]; // allocate contiguous block 100 * sizeof(float) bytes
Aside from this being unnecessary, you leak memory, i.e. you allocate storage in the first statement that you never free before assigning a new value to the pointer that hold the first address to the previously allocated storage.
When allocating memory dynamically using new, you need to make sure you delete it accordingly. For arrays, you need to do the following:
float *output = new float[HighRange]; // allocate
delete [] output; // deallocate, note the delete[] operator
output = new float[10 * 10]; // allocate anew
Note: This is just to display correct usage of new/delete[]. By no means do I suggest your code would be any better if you handled deallocation in your example. :)
lets say i have:
#include <iostream>
using namespace std;
int **a; //Global Variable
int main()
{
n=5;
a = new int*[n];
for ( int i = 0 ; i < n ; i++ )
a[i] = new int[n] ;
}
is there any realloc() method to increase the row size? (column size is fixed)
I mean if the row size is 5 then i wanna make it 6 not much more, just +1.
I use
for(i=0;i<n;i++)
{
counter++;
a[i] = (int *) realloc(a[i],counter*sizeof(int));
}
but i think something is wrong....
Edit: please don't advise any vector or sth like that.. Cuz i need my array as global.
realloc only works when you allocated with malloc. If you used new, you'll have to delete and then use new again (or just use something like a std::vector).
EDIT: Since you asked for an example of how to use malloc:
a = new int*[n];
would become
a = (int **) malloc (n * sizeof (int *));
and
a[i] = new int[n] ;
would become
a[i] = (int *) malloc (n * sizeof (int));
You can write your own routine to resize the array.
If you want a resized block with size N
allocate (new) the new size N
copy old array/block to this newly allocated array/block
free the old array (delete)
To avoid calling this routine again and again, better preallocate a large chunk, the size of chunk will be determined by the need of your application, and should be such which avoid resizing the array a lot of times.
The answer is No!
C++ memory management does not contain functionality for reallocating/resizing allocated memory. You would have to implement such a thing yourself using new/copy/delete semantics
I am trying to call a function that takes char** as a parameter. Its job is to fill an array of strings (i.e. an array of char*). I know the max length of the strings, and I can pass the max number to fill as another parameter, so I was hoping to stack allocate it like this:
fill_my_strings(char** arr_str, int max_str); // function prototype
char fill_these[max_strings][max_chars_per_string]; // allocating chars
fill_my_strings(fill_these, max_strings); // please fill them!
Of course, I get the "cannot convert char[max_strings][max_chars_per_string] to char**" error.
I know this is some subtle (or not-so-subtle) problem with my understanding of the difference between arrays and pointers. I'm just not sure why it's not possible to pass this block of memory to something wanting a char** and have it fill in my stack-allocated chars. Could somebody please explain if this is possible, or if not, why not?
Is it possible to call a function like this without calling malloc / new?
The simple answer to your question is no; a two dimensional array is different than a pointer-to pointer type. Arrays decay to pointers to their first element, but pointers actually are that value.
The difference between these types is clear, if you cast both to char*
int x;
char *arr_pp[] = {"foo", "bar", "baz"};
char arr_2d[][4] = {"foo", "bar", "baz"};
char *cp = (char*)arr_pp;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
cp = (char*)arr_2d;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
The output (on my computer) is:
-80 -123 4
102 111 111
Where the first row is gibberish formed by the fact that I'm printing an address cast into bytes, and the second row is the ascii values of "foo".
In a function taking a char ** the compiler can't know to decay array types, which don't actually contain pointers.
Suppose you have n pointers to strings of m-1 maximum characters (m characters including the NULL).
So, in pure C:
sizeof(char[n][m]) will return n*m.
sizeof(char**) will return the size of a pointer in your architecture, probably 32 (if x86) or 64 (if x86_64).
char[n][m] actually allocates the n*m byte contiguously. char** allocates a single pointer. This pointer references a memory stripe of *n bytes. Each of these n pointers points to a memory stripe of m characters.
So, considering that sizeof(char) == u, if you declare char a[n][m], when you use a[i][j], the compiler understands *(a + i*m*u + j*u).
So, considering that sizeof(char *) == w, if you declare char **a, when you use a[i][j], the compiler understands ((a + i*w) + j*w).
Completely different data management.
The closes thing you could do to handle your special case is to create a char** variable, and populate it with the addresses of your stack allocated matrix.
char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}
I am not sure why fill_my_strings() need a char** parameter. From your example, caller have already allocated the memory from stack. So using a char* should be OK.
But if you want to use char** or you can't modify the fill_my_strings() function, try following example code:
void fill_my_strings(char** arr_str, int max_chars_per_string, int max_strings)
{
for(int i = 0; i < max_strings; ++i)
{
//Make sure you have enough space
memcpy(*arr_str, "ABCD", sizeof("ABCD"));
*arr_str += max_chars_per_string;
}
}
char fill_these[max_strings][max_chars_per_string];
char* pointer = (char*)fill_these;
fill_my_strings(&pointer, max_strings, max_chars_per_string);
The obvious thing to do is build an index
In c use something like:
char string_list[num_strings][str_length];
// ...
char**index = calloc( (num_strings+1), sizeof(*index) ); // calloc insures NULL termination
for (int i=0; i<num_strings; ++i) {
index[i] = string_list[i]
}
In c++ prefer new[] to calloc;