I'm trying to learn more about malloc() and need help clarifying the output. I want to reserve 10 bytes of memory and be able to access them individually but they must be in one block. Here is the code:
#include<iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
int main()
{
char neededbytes = 10;
char *p;
p = (char *)malloc(neededbytes * sizeof(char));
if(p==NULL)
{
cout<<"Error! memory not allocated.";
exit(0);
}
else
{
for (int i = 0; i < neededbytes; i++)
{
p[i] = 0;
}
for (int i = 0; i < neededbytes; i++)
{
cout<<"Address at index " << i << " is ";
cout<<&p+i<<endl;
}
}
free(p);
}
The output of the program shows that all addresses are 8 bytes apart. Shouldn't they be only one byte apart? Is there a way for me to know if char consumes 8 bytes on my architecture?
&p+i is the same as (&p)+(i), and since p has type char*, &p has type char**. As a result, adding i will actually add i * sizeof(char *) bytes to the address denoted by &p.
What you want is p + i, which will add i * sizeof(char) bytes to the address stored in p. In other words, you already have a pointer to contiguous data when you use malloc(). Of course, this is C++, so char * is handled specially by std::cout, std::cerr, and the std::ostream class in general. You'd need to do something like static_cast<void *>(p + i) rather than just p + i as you would use in C.
As others have stated, you should avoid using malloc() and free() in C++ when possible; C++ has the new[] and delete[] operators for your purpose.
cout<<&p+i<<endl; should just be cout<<static_cast<void*>(p+i)<<endl;
It's because you are using the address of operator, the offset will be i * sizeof(char *) in that case which on your system is apparently 8 * i bytes.
Try this instead
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
char neededbytes = 10;
char *p;
p = static_cast<char *>(malloc(neededbytes));
if (p == NULL)
{
cout << "Error! memory not allocated.";
exit(-1);
}
for (int i = 0; i < neededbytes; i++)
p[i] = 0;
for (int i = 0; i < neededbytes; i++)
{
cout << "Address at index " << i << " is ";
cout << static_cast<void *>(p + i) << endl;
}
free(p);
}
You could look at the byte alignment of char in your compiler output settings but I bet char is always 1 byte. Try a few changes like this (I think you are accessing the wrong array element at &p+i) :
int main()
{
int neededbytes = 10;
char *p=NULL;
p = malloc(neededbytes * sizeof(char));
if(p==NULL)
{
cout<<"Error! memory not allocated.";
exit(0);
}
else
{
for (int i = 0; i < neededbytes; i++)
{
p[i] = 0;
}
for (int i = 0; i < neededbytes; i++)
{
cout<<"Address at index " << i << " is ";
// Dave cout<<p+i<<endl;
cout<<&(p+i)<<endl;
}
}
free(p);
}
NB: Dave shared the correct syntax of p+i. Thanks Dave
Change cout<<&p+i<<endl; to cout<<static_cast<void*>(p+i)<<endl;.
Here's a site that talks about memory alignment on GNU systems. It will always be 8(16 for 64 bit systems) byte aligned. There are some libc (stdlib.h) functions that can force alignment for you listed there though.
http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html
Related
Write a function, reverseArray, that when passed an int array of length greater than 0 will return a dynamically allocated array of the same length but with the elements in the reverse order. For example, if passed the array, {1,2,3,4,5,6,7,8,9,0} the function would return the array {0,9,8,7,6,5,4,3,2,1}.
Below is my code, but there is a bug in it.
This is my output.
1
2
3
4
5
6
4113
6
5
4
3
2
1
0x7fffe697ceb0
The 4113 and address are provided by the compiler.
#include <iostream>
using namespace std;
int * readNumbers() {
int * a = new int[6];
for (int i = 0; i < 6; i++) {
int x;
cin >> x;
a[i] = x;
}
// a++;
return a;
delete[] a;
}
int *reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
return numbers1;
delete [] numbers1;
}
int main() {
int *arr1 = readNumbers();
cout << reverseArray(arr1,6) << endl;
return 0;
}
I think there may have been an issue with your wording. Assuming you want your function just to print the reverse of a passed array, you're off to a good start.
One issue is what was said in the comments: your for loop is indexing past your array. When you type int * a = new int[6]; you are creating a pointer 'a' which points to a location in memory. Since you chose size 6, the appropriate amount of memory is allocated. If you happen to index outside of that range, you will end up pointing to a random spot in memory, not allocated for your array. Hence why you are getting a weird number '4113'.
A fix for this could be:
int i = length changed to int i = length-1
Another issue is that your function returns an integer pointer, and you are trying to cout this pointer. As another commenter said, you have to think about what this does. If you try this code:
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 2, 3};
cout << arr << endl;
return 0;
}
your output would be something like 0xff09ba. This represents the location of the start of the array in memory. If you change arr to (arr + 1) you will get the location of the second index of the array.
So when you type cout << reverseArray(arr1,6) << endl; you are really just printing out the location of numbers1 in memory. This is why you are getting '0x7fffe697ceb0' in your output. To fix this, simply make your function
void reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
}
and change your main to:
int main() {
int *arr1 = readNumbers();
reverseArray(arr1,6);
return 0;
}
Now, if you actually want to return this array, you would need to create a new array which holds the reverse numbers and then return that. An example of a function that does that is:
int* reverseArray(int *numbers1,int length) {
int j = 0;
int *numbers2 = new int[length];
for (int i = length-1; i >=0; i--) {
numbers2[j] = numbers1[i];
j++;
}
return numbers2;
}
There are probably better ways to do this, but this is just one solution. Regardless, you should always be careful when allocating memory yourself.
Can anyone please tell what is the issue in code?
It gives me correct output but at the end i ma getting error " Below code gives me error * stack smashing detected *:"4
I used GDB to check I get signal at the end as
__stack_chk_fail () at stack_chk_fail.c:28
28 stack_chk_fail.c: No such file or directory.
#include <iostream>
#include <string.h>
#include <iomanip>
using namespace std;
void computeLps (char p[], int n) {
int *lps = new int[n];
int len = 0;
lps[0] = 0;
int i = 1;
while(i < n)
{
/* code */
if(p[len] == p[i]){
len ++;
lps[i] = len;
i++;
}
else {
if(len != 0) {
len = lps[len - 1];
}
else{
lps[i] = 0;
i++;
}
}
}
for (int i = 0; i < n; ++i)
{
/* code */
cout << lps[i]<<" ";
}
cout <<endl;
}
int main() {
char b[] = "ABABDABACDABABCABAB";
char a[] = "ABABCABAB";
strcat (b,"$");
strcat (b,a);
//cout << b;
computeLps(b,strlen(b));
return 0;
}
Because you used an array of characters for b, the memory allocated to your array b on the stack is fixed. If you want to avoid this, make the char array large enough to be added to or try using std::string and concatenate with the tips in this link.
How to concatenate two strings in C++?
std::string will dynamically allocate memory and grow when it needs to if the memory allocated for it is all used.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am running below code and i am getting output as 8 0 4, rather 8 9 4. Can you please help me understand the problem with this code-
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
int *p;
p = (int*)calloc(2, sizeof(int));
*(p + 0) = 8;
*(p + 1) = 9;
p = (int*)realloc(p, 3);
*(p + 2) = 4;
for (int i = 0; i < 3; i++)
cout << p[i] << " ";
free(p);
p = NULL;
}
The realloc function needs the size on bytes and not elements.
You need to do
int *temp = realloc(p, 3 * sizeof(*temp));
if (temp == NULL)
{
// Handle error...
}
p = temp;
Note that I use a temporary variable for the result of realloc. This is because if realloc fails it will return NULL and reassigning the result back to the pointer you pass as the first argument then you will lose the original pointer.
The size specified as an argument to realloc() must be computed as a number of bytes. As you found out yourself, the simple fix is
p = (int*)realloc(p, 3 * sizeof(int));
Incidentally, you could use the type of *p instead of int to avoid potential inconsistencies if the type of p changes later:
p = (int*)realloc(p, 3 * sizeof(*p));
But since the cast is needed in C++, the inconsistency at least be visible.
You should also test whether calloc() and realloc() succeeded. They do not throw exception but return NULL when out of memory.
Note that you should decide whether you program in C or C++. These languages have a common ancestry but have diverged notably and some idioms used in one are considered bad style in the other, as more appropriate and safer constructs are available.
Here is a corrected version of your program in C:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = calloc(2, sizeof(*p));
assert(p != NULL);
*(p + 0) = 8;
*(p + 1) = 9;
p = realloc(p, 3 * sizeof(*p));
assert(p != NULL);
*(p + 2) = 4;
for (int i = 0; i < 3; i++) {
printf("%d ", p[i]);
}
putchar('\n');
free(p);
return 0;
}
While here is C++ program by PaulMcKenzie that implements the same thing, although the use of pointer p is still frowned upon:
#include <vector>
#include <iostream>
using namespace std;
int main() {
std::vector<int> pV(2);
int *p = pV.data();
*(p + 0) = 8;
*(p + 1) = 9;
pV.resize(3);
p = pV.data();
*(p + 2) = 4;
for (int i = 0; i < 3; i++) {
cout << p[i] << " ";
}
}
As you can see, std::vector<int>::resize() takes the number of elements, no need to compute byte counts.
Using pointers and especially pointer arithmetic is not good practice in C++, a much simpler version is:
#include <vector>
#include <iostream>
using namespace std;
int main() {
std::vector<int> v(2);
v[0] = 8;
v[1] = 9;
v.resize(3);
v[2] = 4;
for (int i = 0; i < 3; i++) {
cout << v[i] << " ";
}
}
You could also use an enumerator for the printout.
Ok, I got the problem:
p = (int*)realloc(p, 3);
the size value I had specified was 3, it should have been 3 * sizeof(int)
I was testing the new operator in C++ as the following:
#include <iostream>
using namespace std;
int main()
{
int *Q = new int[5];
Q[0] = 0;
Q[1] = 1;
Q[2] = 2;
Q[3] = 3;
Q[4] = 4;
for (int i = 0; i < 7; i++)
{
cout << "Q[" << i << "] = " << Q[i] << endl;
}
return 0;
}
If you notice, in the for loop I am exceeding the limit of the pointer and I was expecting an stack over flow type of error; but instead of that it just printed what ever these two extra locations have.
Does any one have explanation about this ?
Yes, what is happening is that your program is "walking off" the end of an array, and is printing out garbage. "Garbage" in this context can be anything in the computer (memory, etc.). It does not have protections against this like Java or Python does.
i have following code for allocation two dimensional array
#include <iostream>
using namespace std;
int **malloc2d(int r,int c){
int **t=new int*[r];
for (int i=0;i<r;i++)
t[i]=new int[c];
for (int i=0;i<r;i++){
for (int j=0;j<c;j++){
t[i][j]=i+j;
}
}
return t;
}
int main(){
int m=10;
int n=10;
int **a=malloc2d(m,n);
for (int i=0;i<m;i++){
for (int j=0;j<n;j++){
cout<<a[i][j]<< " ";
cout<< " \n";
}
cout<< " \n";
}
return 0;
}
it works but my question is: how good is this code according to performance efficienty or according to code speed? thanks
With an int ** you have lots of pointers to tiny (4 byte) memory spaces which is inefficient due to malloc overhead (every malloc implementation has an overhead, the minimum normally is sizeof(void*) AFAIK which in your case would mean there's at least a 100% overhead for all "cells").
As an alternative, you could use a one-dimensional array and calculate the indexes yourself like this: index = (row * num_columns) + column. You would lose the nice a[row][column] notation, though. Still, it should be faster to access as well because in your (clean) solution there have to be two pointer dereferences (memory operations) while in the way I suggest you only have one. It would look something like this:
#include <iostream>
using namespace std;
inline int a_index(int row, int column, int column_size) {
return((row * column_size) + column);
}
int *malloc2d(int r,int c) {
int *t=new int[r * c];
for (int i=0;i<r;i++){
for (int j=0;j<c;j++){
t[a_index(i,j,c)]=i+j;
}
}
return t;
}
int main(){
int m=10;
int n=10;
int *a=malloc2d(m, n);
for (int i=0;i<m;i++){
for (int j=0;j<n;j++){
cout<<a[a_index(i,j,n)]<< " ";
cout<< " \n";
}
cout<< " \n";
}
return 0;
}
I assume you plan to add delete[], or the program will terminate before leakage matters.
Anyway, it won't be very efficient.
First, the array will be composed of non-contiguous blocks of memory. That makes it harder for the machine's memory subsystem to handle.
Second, some extra space is being wasted to hold the array of pointers.
Just do it the old fashioned way:
int *a = new int[ r * c ];
or with vector
std::vector<int> a( r * c );
and compute indexes as ever:
cout << a[ i * c + j ] << ' ';
However, since you are looping over the entire array, you could ignore the two-dimensionality except for formatting:
for ( int i = 0; i < r * c; ++ i ) {
cout << a[ i ] << ' ';
if ( i % c == c-1 ) cout << '\n';
}
If you don't delete the memory that you have allocated by using new, then you will leak memory.