c++ unsigned char array allocation - segmentation fault - c

I can't figure out what seems to be the problem that I get a segmentation fault from this:
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
void alloc(unsigned char *data) {
data = (unsigned char *) malloc(20);
memset(data, 0, 20);
}
void main() {
unsigned char *data = NULL;
int i;
alloc(data);
for (i = 0; i < 20; i++) {
data[i] = i;
printf("%d ", *(data + i));
}
free(data);
}
Unsigned char is 1 byte so the loop through 20 should be correct

void alloc(unsigned char *data) {
data = (unsigned char *) malloc(20);
memset(data, 0, 20);
}
modifies a local copy of your pointer. You could pass it by reference to make your example work:
void alloc(unsigned char *&data) {
data = (unsigned char *) malloc(20);
memset(data, 0, 20);
}

It seems that your program is written in C instead of C++. In C++ you should use operator new [] instead of malloc.
The problem with the function is that function parameters are its local variables. So the function parameter char *data is a copy of its argument declared in main like
unsigned char *data = NULL;
So any changes of the parameter in function alloc do not influence on the original argument. After exiting the function the parameter (local variable) will be destroyed and the original variable in main will not be changed.
You have two approaches. Either you declare the function the following way
void alloc(unsigned char **data) {
*data = (unsigned char *) malloc( 20 );
if ( *data ) memset( *data, 0, 20 );
}
and call it like
alloc( &data );
Or you declare the function the following way
unsigned char * alloc() {
unsigned char *data = (unsigned char *) malloc( 20 );
if ( data ) memset( data, 0, 20 );
return data;
}
and call it in main like
data = alloc();
Take into account that function main shall be decalred in C like
int main( void )
^^^
and in C++ like
int main()
^^^

You could also return the pointer, rather than passing it to the function.
unsigned char *alloc() {
unsigned char *data = (unsigned char *) malloc(20);
memset(data, 0, 20);
return data;
}
And then,
...
unsigned char *data = alloc();
int i;
...
You tagged C++, but your code looks like C. If you really are trying to write C++ you shouldn't be using malloc. Either use new[] or the appropriate smart pointers.
EDIT: You're using void main(). Don't do that.
What should main() return in C and C++?

Related

Use realloc() after malloc() to change the size of unsigned char array

In the main function, I use malloc() to create an unsigned char array:
int main()
{
int length = 64;
unsigned char *array = (unsigned char *)malloc(length * sizeof(unsigned char));
...
change_size(array, length);
}
change_size() defined in .h:
void change_size(unsigned char* arr, int len);
In the change_size function, I will use realloc() to increase the array size:
void change size(unsigned char* arr, int len)
{
printf("%d\n", len);
len = len + 16;
printf("%d\n", len);
arr = (unsigned char *)realloc(arr, len * sizeof(unsigned char));
int new_len = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", new_len);
}
The printf() show me:
64
80
8
The array size in the main() also needs to be updated.
Then how to change this array size correctly?
You need to pass your parameters as pointers if you want to change their value back in the caller. That also means you pass your array pointer as a pointer, because realloc might change it:
int change_size(unsigned char **arr, int *len)
{
int new_len = *len + 16;
unsigned char *new_arr = realloc(*arr, new_len);
if (new_arr) {
*len = new_len;
*arr = new_arr;
}
return new_arr != NULL;
}
Here I've modified change_size to suit, and also added a return value to indicate success, since realloc can fail to resize the memory. For clarity, I removed the printf calls. Oh, and I also removed the cast, since that is not valid in C.
Example usage:
if (!change_size(&array, &len))
{
perror("change_size failed");
}
One final note is that you can use your change_size function for the first allocation too, rather than calling malloc. If the first argument to realloc is NULL, it does the same thing as malloc.
First C is not babysitter language,
You only need basic things then you can do everything,
Just try hard to totally understand basic.
#include <stdio.h>
#include <stdlib.h>
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
free(G1);
return 0;
}
Okay I answer it. #Chipster
#include <stdio.h>
#include <stdlib.h>
int change_size(char** arr, int len)
{
char* nar=(char*)malloc(sizeof(char)*(len+16));
if(nar){
free(* arr);
*arr=nar;
nar[10]='K';//this will let you know its right
return len+16;
}
return len;
}
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
printf("%d\n",G1);
G1_Len=change_size(&G1,G1_Len);
printf("%c\n",G1[10]);
printf("%d\n",G1);
printf("%d\n",G1_Len);
free(G1);
return 0;
}

C Program: Update unsigned char pointer array with function

I have a function to update an unsigned char* and cannot find where my bug is. I'm not sure if I need to allocate memory, or if I am pointing to the wrong memory space somewhere. I tried to follow a similar structure as posted here, but have not had success with an unsigned char.
My code so far:
#include <stdio.h>
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
*arr = ptr;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
int main(int argc, const char* argv[])
{
int i = 0;
unsigned char *blah;
unsigned char ptr2[3] = {103, 104, 105};
blah = ptr2;
printf("Blah is: \n");
for (i = 0; i < 3; i++) {
printf("%d,",*(blah+i)); //This prints out 103,104,105
}
changeArray(&blah);
printf("Blah is now: \n");
for (i = 0; i < 3; i++) {
printf("%d,", *(blah +i)); //This prints out 0,0,0
}
return 0;
}
Any help in determining how to properly access the values set in the changeArray() function would be greatly appreciated.
With this *arr = ptr; you are storing a pointer to a variable with automatic storage duration. The behaviour undefined.
You can dynamically allocate and return a pointer that way:
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
unsigned char *p = malloc(sizeof ptr);
memcpy(p, ptr, sizeof ptr);
*arr = p;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
You should also do error checking if malloc failed and remember to free the allocated memory after use in main.
The problem here is, ptr is local to changeArray() function. So once the function finishes execution, there is no existance of ptr. Hence, once you assign ptr to *arr
*arr = ptr;
and changeArray() execution gets over, accessing blah in main() now will invoke undefined behaviour.
FWIW, you don't need to pass the address of blah, you don't need a pointer-to-pointer at all. blah is already a pointer, which you can pass to changeArray() to alter the contents of the memory area it points to. You can do something like
void changeArray(unsigned char *arr)
{
for (int i = 0; i < 3; i ++)
arr[i] = 100+i;
}
and call it like
changeArray(blah);

Do you have a simple bzero example?

I need to implement bzero, I've read the manual, I saw a lot of posts about it on StackOverflow, but what I'm asking for is a simple example where you use bzero, I didn't find any simple example of using bzero instead of using it in server/client in C.
Ok so this is my memset:
void *my_memset(void *b, int c, size_t len)
{
char *pb;
unsigned char car;
if (b == NULL)
return (NULL);
pb = b;
car = (unsigned char)c;
while (len--)
{
*pb++ = car;
}
return (b);
}
void ft_bzero(void *s, size_t n)
{
ft_memset(s, 0, n);
}
Looks fine?
All bzero() does is memset everything to zero.
myStruct_t * foo = malloc (sizeof(myStruct_t));
bzero(foo, sizeof(myStruct_t));
// All bytes of foo are now 0
It's no different from calling
memset (foo, 0, sizeof(myStruct_t));
Under the hood, bzero() should match this implementation...
void bzero(void * s, size_t n)
{
char * c = s; // Can't work with void *s directly.
size_t i;
for (i = 0; i < n; ++i)
c[i] = '\0';
}
The simplest example:
char *test = malloc(256);
memset(test, 0, 256); // or bzero(test, 256);
This will set all elements of test to zero.
Notice that memset returns a pointer when bzero don't. So if you want to reproduce the bzero(), this would probably be more like :
void ft_bzero(void *s, size_t n)
{
unsigned char *ptr;
while (n-- > 0)
*ptr++ = 0;
}

Returning a 2D char array in C

I messed around with this enough but I really don't get it.
Here is what I want to do: Take a 2D char array as an input in a function, change the values in it and then return another 2D char array.
That's it. Quite simple idea, but ideas do not get to work easily in C.
Any idea to get me started in its simplest form is appreciated. Thanks.
C will not return an array from a function.
You can do several things that might be close enough:
You can package your array in struct and return that. C will return structs from functions just fine. The downside is this can be a lot of memory copying back and forth:
struct arr {
int arr[50][50];
}
struct arr function(struct arr a) {
struct arr result;
/* operate on a.arr[i][j]
storing into result.arr[i][j] */
return result;
}
You can return a pointer to your array. This pointer must point to memory you allocate with malloc(3) for the array. (Or another memory allocation primitive that doesn't allocate memory from the stack.)
int **function(int param[][50]) {
int arr[][50] = malloc(50 * 50 * sizeof int);
/* store into arr[i][j] */
return arr;
}
You can operate on the array pointer passed into your function and modify the input array in place.
void function(int param[][50]) {
/* operate on param[i][j] directly -- destroys input */
}
You can use a parameter as an "output variable" and use that to "return" the new array. This is best if you want the caller to allocate memory or if you want to indicate success or failure:
int output[][50];
int function(int param[][50], int &output[][50]) {
output = malloc(50 * 50 * sizeof int);
/* write into output[i][j] */
return success_or_failure;
}
Or, for the caller to allocate:
int output[50][50];
void function(int param[][50], int output[][50]) {
/* write into output[i][j] */
}
You cannot return an array from a function.
You have several options:
wrap arrays inside structs
struct wraparray {
int array[42][42];
};
struct wraparray foobar(void) {
struct wraparray ret = {0};
return ret;
}
pass the destination array, as a pointer to its first element (and its size), to the function; and change that array
int foobar(int *dst, size_t rows, size_t cols, const int *src) {
size_t len = rows * cols;
while (len--) {
*dst++ = 42 + *src++;
}
return 0; /* ok */
}
// example usage
int x[42][42];
int y[42][42];
foobar(x[0], 42, 42, y[0]);
change the original array
int foobar(int *arr, size_t rows, size_t cols) {
size_t len = rows * cols;
while (len--) *arr++ = 0;
return 0; /* ok */
}
char **foo(const char * const * bar, size_t const *bar_len, size_t len0) {
size_t i;
char** arr = malloc(sizeof(char *) * len0);
for (i = 0; i < len0; ++i) {
arr[i] = malloc(bar_len[i]);
memcpy(arr[i], bar[i], bar_len[i]);
}
/* do something with arr */
return arr;
}
Somewhere else in your code:
char **pp;
size_t *pl;
size_t ppl;
/* Assume pp, pl are valid */
char **pq = foo(pp, pl, ppl);
/* Do something with pq */
/* ... */
/* Cleanup pq */
{
size_t i;
for (i = 0; i < ppl; ++i)
free(pq[i]);
free(pq);
}
Because you're passing by-pointer instead of by-value and you want to write to the input array, you have to make a copy of it.
Here's another example. Tested and works.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void test(char**,unsigned int,unsigned int);
const unsigned int sz_fld = 50 + 1;
const unsigned int sz_ffld = 10;
int main(void) {
char fld[sz_ffld][sz_fld];
for (unsigned char i=0;i<sz_ffld;++i) {
strcpy(fld[i],"");
}
strcpy(fld[0],"one");
strcpy(fld[1],"two");
strcpy(fld[2],"three");
char** pfld = malloc(sz_ffld*sizeof(char*));
for (unsigned int i=0;i<sz_ffld;++i) {
*(pfld+i) = &fld[i][0];
}
test(pfld,sz_ffld,sz_fld);
printf("%s\n",fld[0]);
printf("%s\n",fld[1]);
printf("%s\n",fld[2]);
free(pfld);
return(0);
}
void test(char** fld,unsigned int m,unsigned int n) {
strcpy(*(fld+0),"eleven");
strcpy(*(fld+1),"twelve");
return;
}
Note the following:
For compiling, I am using gcc with the C99 option.
I defined the function to include the two sizes information, but I wrote very basic code and am not actually using the information at all, just the strcpy(), so this certainly is not security-safe code in any way (even though I'm showing the "m" and "n" for such facility). It merely shows a technique for making a static 2D char array, and working with it in a function through the intermediate of an array of pointers to the "strings" of the array.
When you pass a 2D array to a function as a parameter, you need to explicitly tell it the size of the arrays second dimension
void MyFunction(array2d[][20]) { ... }
The following will do what you want. it will print "One" and "Ten". Also note that it is typed to the exact array dimensions of 10 and 8.
char my_array[10][8] =
{
{"One"},
{"Two"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"Nine"},
{"Ten"},
};
void foo ( char (**ret)[10][8] )
{
*ret = my_array;
}
void main()
{
char (*ret)[10][8];
foo(&ret);
printf("%s\r\n", (*ret)[0] )
printf("%s\r\n", (*ret)[9] )
}
The original question was about RETURNING the array, so I'm updating this to show returning a value. You can't "return an array" directly, but you CAN make a typedef of an array and return that...
char my_array[10][8];
typedef char ReturnArray[8];
ReturnArray* foo()
{
return my_array;
}

Generic editable functions in C using void*

I fall in some problem.
I need to write some function like memcpy(void*, const void*), which its signature should be:
void arrayCopy(void *dest, int dIndex, const void *src, int sIndex, int len)
I noticed that, in many implementation of memcpy, we cast void* to char*, but I think this is not the case of me, as the arrayCopy function needed to be used on arrays of many types including structs.
So, how can I accomplish this?
EDIT:
the source code might be something like that:
#include <stdio.h>
#include <string.h>
void arrayCopy(void *, int, const void *, int, int, size_t);
int main(void)
{
int i;
int dest[10] = {1};
int src [] = {2, 3, 4, 5, 6};
arrayCopy(dest, 1, src, 0, 5, sizeof(int));
for (i=0; i<10; i++) printf("%i\n", dest[i]);
return 0;
}
void arrayCopy(void *dest, int dIndex, const void *src, int sIndex, int len, size_t size)
{
char *cdest = (char*) dest;
const char *csrc = (char*) src;
int i;
len *= size;
if (dest == src)
{
printf("Same array\n");
}else
{
cdest += (dIndex * size);
csrc += (sIndex * size);
for (i=0; i<len; i++)
*cdest++ = *csrc++;
}
}
Thanks.
"char * " is just a bunch bytes, everything in C is ultimately bytes - you can cast a pointer to any data structure to char* (you will also need to know the size in memory of the structure)
The function must have an element-size info, eg:
void *arrayCopy(void *dest, size_t di,const void *src, size_t si, size_t num, size_t esize)
{
char *cdest = (char*) dest;
const char *csrc = (char*) src;
return memcpy( &cdest[esize*di], &csrc[esize*si], esize*num );
}
...
arrayCopy(dest, 1, src, 0, 5, sizeof*src);
You cannot work with objects of type void. The Standard doesn't allow that. So you need to cast the void away, and the best type to use is unsigned char. There's a guarantee by the Standard that unsigned char can access all bits of any other type representable in your system.

Resources