I'm having a bit of a problem with strcat and segmentation faults. The error is as follows:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00007fff82049f1f in __strcat_chk ()
(gdb) where
#0 0x00007fff82049f1f in __strcat_chk ()
#1 0x0000000100000adf in bloom_operation (bloom=0x100100080, item=0x100000e11 "hello world", operation=1) at bloom_filter.c:81
#2 0x0000000100000c0e in bloom_insert (bloom=0x100100080, to_insert=0x100000e11 "hello world") at bloom_filter.c:99
#3 0x0000000100000ce5 in main () at test.c:6
bloom_operation is as follows:
int bloom_operation(bloom_filter_t *bloom, const char *item, int operation)
{
int i;
for(i = 0; i < bloom->number_of_hash_salts; i++)
{
char temp[sizeof(item) + sizeof(bloom->hash_salts[i]) + 2];
strcat(temp, item);
strcat(temp, *bloom->hash_salts[i]);
switch(operation)
{
case BLOOM_INSERT:
bloom->data[hash(temp) % bloom->buckets] = 1;
break;
case BLOOM_EXISTS:
if(!bloom->data[hash(temp) % bloom->buckets]) return 0;
break;
}
}
return 1;
}
The line with trouble is the second strcat. The bloom->hash_salts are part of a struct defined as follows:
typedef unsigned const char *hash_function_salt[33];
typedef struct {
size_t buckets;
size_t number_of_hash_salts;
int bytes_per_bucket;
unsigned char *data;
hash_function_salt *hash_salts;
} bloom_filter_t;
And they are initialized here:
bloom_filter_t* bloom_filter_create(size_t buckets, size_t number_of_hash_salts, ...)
{
bloom_filter_t *bloom;
va_list args;
int i;
bloom = malloc(sizeof(bloom_filter_t));
if(bloom == NULL) return NULL;
// left out stuff here for brevity...
bloom->hash_salts = calloc(bloom->number_of_hash_salts, sizeof(hash_function_salt));
va_start(args, number_of_hash_salts);
for(i = 0; i < number_of_hash_salts; ++i)
bloom->hash_salts[i] = va_arg(args, hash_function_salt);
va_end(args);
// and here...
}
And bloom_filter_create is called as follows:
bloom_filter_create(100, 4, "3301cd0e145c34280951594b05a7f899", "0e7b1b108b3290906660cbcd0a3b3880", "8ad8664f1bb5d88711fd53471839d041", "7af95d27363c1b3bc8c4ccc5fcd20f32");
I'm doing something wrong but I'm really lost as to what. Thanks in advance,
Ben.
I see a couple of problems:
char temp[sizeof(item) + sizeof(bloom->hash_salts[i]) + 2];
The sizeof(item) will only return 4 (or 8 on a 64-bit platform). You probably need to use strlen() for the actual length. Although I don't think you can declare it on the stack like that with strlen (although I think maybe I saw someone indicate that it was possible with newer versions of gcc - I may be out to lunch on that).
The other problem is that the temp array is not initialized. So the first strcat may not write to the beginning of the array. It needs to have a NULL (0) put in the first element before calling strcat.
It may already be in the code that was snipped out, but I didn't see that you initialized the number_of_hash_salts member in the structure.
You need to use strlen, not sizeof. item is passed in as a pointer, not an array.
The line:
char temp[sizeof(item) + sizeof(bloom->hash_salts[i]) + 2];
will make temp the 34x the length of a pointer + 2. The size of item is the size of a pointer, and the sizeof(bloom->hash_salts[i]) is currently 33x the size of a pointer.
You need to use strlen for item, so you know the actual number of characters.
Second, bloom->hash_salts[i] is a hash_function_salt, which is an array of 33 pointers to char. It seems like hash_function_salt should be defined as:
since you want it to hold 33 characters, not 33 pointers. You should also remember that when you're passing a string literal to bloom_filter_create, you're passing a pointer. That means to initialize the hash_function_salt array we use memcpy or strcpy. memcpy is faster when we know the exact length (like here):
So we get:
typedef unsigned char hash_function_salt[33];
and in bloom_filter_create:
memcpy(bloom->hash_salts[i], va_arg(args, char*), sizeof(bloom->hash_salts[i]));
Going back to bloom_operation, we get:
char temp[strlen(item) + sizeof(bloom->hash_salts[i])];
strcpy(temp, item);
strcat(temp, bloom->hash_salts[i]);
We use strlen for item since it's a pointer, but sizeof for the hash_function_salt, which is a fixed size array of char. We don't need to add anything, because hash_function_salt already includes room for a NUL. We use strcpy first. strcat is for when you already have a NUL-terminated string (which we don't here). Note that we drop the *. That was a mistake following from your incorrect typedef.
Your array size calculation for temp uses sizeof(bloom->hash_salts[i]) (which is
just the size of the pointer), but then you dereference the pointer and try
to copy the entire string into temp.
First, as everyone has said, you've sized temp based on the sizes of two pointers, not the lengths of the strings. You've now fixed that, and report that the symptom has moved to the call to strlen().
This is showing a more subtle bug.
You've initialized the array bloom->hash_salts[] from pointers returned by va_arg(). Those pointers will have a limited lifetime. They may not even outlast the call to va_end(), but they almost certainly do not outlive the call to bloom_filter_create().
Later, in bloom_filter_operation(), they point to arbitrary places and you are doomed to some kind of interesting failure.
Edit: Resolving this this requires that the pointers stored in the hash_salts array have sufficient lifetime. One way to deal with that is to allocate storage for them, copying them out of the varargs array, for example:
// fragment from bloom_filter_create()
bloom->hash_salts = calloc(bloom->number_of_hash_salts, sizeof(hash_function_salt));
va_start(args, number_of_hash_salts);
for(i = 0; i < number_of_hash_salts; ++i)
bloom->hash_salts[i] = strdup(va_arg(args, hash_function_salt));
va_end(args);
Later, you would need to loop over hash_salts and call free() on each element before freeing the array of pointers itself.
Another approach that would require more overhead to initialize, but less effort to free would be to allocate the array of pointers along with enough space for all of the strings in a single allocation. Then copy the strings and fill in the pointers. Its a lot of code to get right for a very small advantage.
Are you sure that the hash_function_salt type is defined correctly? You may have too many *'s:
(gdb) ptype bloom
type = struct {
size_t buckets;
size_t number_of_hash_salts;
int bytes_per_bucket;
unsigned char *data;
hash_function_salt *hash_salts;
} *
(gdb) ptype bloom->hash_salts
type = const unsigned char **)[33]
(gdb) ptype bloom->hash_salts[0]
type = const unsigned char *[33]
(gdb) ptype *bloom->hash_salts[0]
type = const unsigned char *
(gdb)
Related
I try something like below but all the time I have a segmentation fault.
I don't really want to use (e.g.) #define N 1000 and then declare int buffer[N].
Just in case..I'm not allowed to use any headers except stdio.h as well as dynamic memory.
void input (int *buffer, int *length);
int main()
{
int length, *buffer = NULL, *numbers = NULL;
input(buffer, &length);
}
void input(int *buffer, int *length) {
scanf("%d", length);
if (*length < 0) {
error = 1;
return;
}
for (int i = 0; i < *length; i++) {
scanf("%d", *buffer[i]);
}
}
How to pass an array with unknown 1-d dimension into function
In C, arrays cannot exist until their size is known.
There are other approaches though.
In C, code cannot pass an array to a function. some_function(some_array) converts the array some_array to the address of the first element of the array: &some_array[0]. That is what the function receives, a pointer, not an array. The original size information of the array is not passed, thus also pass the length to the function.
Sample:
Read desired length.
{
int length = 0;
scanf("%d", &length);
Form a variable length array, length >= 1.
if (length <= 0) {
return NULL;
}
int buffer[length];
Now call a function, passing the length and the address of the first element of the array.
// Do stuff with length and buf, like read data
foo1(length, buffer);
// foo1() receives the length & address of the first element of the array as an int *
// Do more stuff with length and buf, like write data
foo2(length, buffer);
}
At the end of the block }, buffer no longer available.
In C, you can't create an array if you can't know its size at compile time (or at least not in certain implementations and standards), so doing something like buffer[length] won't work (again at least not in certain implementations/standards).
What you need to do to make sure this works everywhere is to use a pointer (as I see you're trying to use here). However, what you're doing wrong here that causes your segfault with the pointers is you assign them the value of NULL. This also won't work due to how when you assign a pointer an arbitrary value, there is no memory allocated for the pointer (This applies for everything other than addresses of "regular" variables using the & operator and assigning other pointers that are checked to be OK). Your pointers are just pointing to address 0 and can't be used for anything.
What you need to do here to fix the pointers is to use dynamic memory allocation, so you can have a truly variable-sized array. Specifically, you need to use a function like malloc or calloc to allocate memory for the pointers so they are usable. In your case, using calloc and reading its documentation, we see that it takes 2 parameters: The number of elements it should allocate memory for and the size of each element. We also know that it returns a pointer to the starting address of the allocated memory and that in case of failure (which can only happen if you're out of memory), it returns NULL. Using this, we understand that in your case the call to calloc would be like this:
int *buffer = (int *) calloc(length, sizeof(int));
The sizeof() function returns the size of a data type in bytes. Here you allocated enough memory for the pointer to hold length integers (since you'll use it as an array you need enough memory for all the integers, you're not just pointing to 1 integer but storing all of them), and calloc is also noted to initialize every allocated element to 0, so you have an array of integers that are all initialized to 0 (Also note that type casting has been used to make sure the allocated memory block is appropriate for use with an integer array, you can read more about type casting in this small article from Tutorialspoint if you'd like). Then, after this has been allocated, you can start reading your integers into the array. The complete code looks like this:
void input (int *buffer, int *length);
int main() {
// NOTE: I don't see the numbers pointer used here, maybe remove it?
int length, *buffer, *numbers;
input(buffer, &length);
}
void input(int *buffer, int *length) {
scanf("%d", length);
if (*length < 0) {
// Consider printing the exact error here
error = 1;
return;
}
buffer = (int *) calloc(length, sizeof(int));
if (buffer == NULL) {
printf("Couldn't allocate memory for buffer\n");
error = 1;
return;
}
// Accessing the elements of an array doesn't need * and in fact * here can (and probably will) cause terrible things
for (int i = 0; i < *length; i++) {
scanf("%d", buffer[i]);
}
}
Also don't forget to call free() on the pointer after you're done using it to avoid memory leaks (in your case that'd be after the call to input()).
Hope this helped, good luck!
You cannot use arrays because their memory size must be known to the compiler at compile time. Also you can't use Variable Length Arrays because they are allocated at the point of declaration and deallocated when the block scope containing the declaration exits.
The solution to your problem might be to use malloc
I have code which already works but am trying to extend it.
unsigned char **data_ptr;
Allocate memory for the first "array"
data_ptr = (unsigned char **)malloc(sizeof(unsigned char **) * no_of_rows);
Then in a loop initialize each row
data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*), rowsize));
I then pass the address of my array to a library function. It works fine if I just pass the start of a row...
LibFunction( info_ptr, &data_ptr[index] ) //OK
But I need to pass the address of where in a row I want the function to begin writing data.
These both compile but fail in operation
LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1);
or..
LibFunction( info_ptr,(unsigned char **)data_ptr[index][1]);
LibFunction is of the form
LibFunction(..., unsigned char **)
I'm allocating more memory than I need with rowsize so I don't think I'm overrunning the array. As I stated, the code works fine if I pass it the start of a row but bugs out if I
try to pass any other element. There may be something else wrong but I need to know first if my syntax is ok.
Can't find anything else on the net as regards passing the address of single element of dynamic 2d array.
LibFunction( info_ptr,(unsigned char **)data_ptr[index] + 1);
is wrong because data_ptr is an unsigned char **, so data_ptr[index] is an unsigned char *. Leave out the cast and correct the function you're calling, it should accept an unsigned char *.
Some corrections in your program, observed from the top few lines
Since,
unsigned char **data_ptr; // a pointer to a char pointer
get the sizeof(char*) and always avoid typecasting the pointer returned by malloc()
data_ptr = malloc(sizeof(unsigned char *) * no_of_rows);
And for doing the allocation for the rows,
data_ptr[index] = (unsigned char *)malloc(sizeof(unsigned char*)* rowsize));
To pass the address of where in a row you want the function to begin writing data, change the function signature as
LibFunction(..., unsigned char *)
It should be LibFunction(&data_ptr[row][start_here]), exactly the same as if it was just an unsigned char[ROWS][COLUMNS];.
In general, it is my experience that if you think you require casts in modern-day C, it is probable that you are muddled up with what you are trying to do. A nice read is a comment on a post by Linus Torvalds on /. on this kind of stuff.
You're not allocating room for no_of_rows pointers to pointers; there's an asterisk too many in there. Also, you really [shouldn't cast the return value of malloc(), in C][1].
Your first allocation should be:
data_ptr = malloc(no_of_rows * sizeof *data_ptr);
But I need to pass the address of where in a row I want the function to begin writing data
So let's start simple, to make an array the correct size, forget trying to get the sizeof a complex type, we can simply do this:
unsigned char **data_ptr;
data_ptr = malloc(sizeof(data_ptr) * no_of_rows); //Just sizeof your var
Now you've got the correct memory malloc'd next you can malloc the memory for the rest easily:
for(index = 0; index < no_of_rows; index++)
data_ptr[index] = malloc(sizeof(unsigned char*) * rowsize);
Last point, now that we've got all that set up, you should initialize your array:
for(index = 0; index < no_of_rows; index++)
for(index2 = 0; index2 < rowsize; index2++)
data_ptr[index][index2] = 0;
As for your function, you want it to take a "portion" of an array, so we need it to take an array and a size (the length of the array to initialize):
void LibFunction(unsigned char data[], int size);
Then we're your ready to store some data it's as easy as:
LibFunction(&data_ptr[1][2], 3); // store data in second row, 3rd column, store
// three values.
You can do something like this:
unsigned char* ptr = &data[0][1];
LibFunction(info_ptr, &ptr);
I have an array of names stored in char *namelist[]. When I pass it to a function, I'm unable to display all of the names in the namelist:
int ReadListOfName(const char* names[])
{
//Note: I always get the len = 1
// Anyway I can get total items in names
int len = sizeof(names)/sizeof(char*);
for (i=0; i<len; i++)
printf("%d-%s\n",i,names[i]);
return 0;
}
int main(void)
{
const char* names[] = {"a","b","c"};
ReadListOfName(names);
return 0;
}
What's the problem?
int len = sizeof(names)/sizeof(char*);
This doesn't get you the number of elements, sizeof doesn't do what you want on pointers. You have to pass the length as an additional argument to the function. Also discussed in this C FAQ. You could try:
int ReadListOfName(const char* names[], size_t len)
/* ... */
ReadListOfName(names, sizeof(names)/sizeof(names[0]));
int ReadListOfName(const char* names[])
In this names essentially becomes char ** rather than char * [] as defined your main.
You'll need to pass in another argument to ReadListOfName specifying the length of the array or have a terminating value in your array like argv does. When passed to a function, an array will decay to a pointer; a char*[] will decay to a char**, as you're passing the address of the first element in the array. Therefore your function is in fact interpreted as:
int ReadListOfName(const char **names)
And you're actually equating sizeof(char**)/sizeof(char*), which won't give you the number of elements in the array (it'll probably give you 1).
Add a length argument and then just calculate len before passing it ReadListOfName.
Note that rather than dividing sizeof(names) by sizeof(char*) to get the number of elements in the array, you can instead divide by sizeof(*names), and you wouldn't need to worry about changing char* if you change the type of the elements in names:
int len = sizeof(names)/sizeof(*names);
As the other answers already explain what happens to the array reference when passing it to the function, please find an approach to solve the issue without adding another parameter to the method printing the names.
You might like to add a stopper element to your list like so:
#include <stdio.h>
int ReadListOfName(const char ** names)
{
for (int i=0; names[i]; i++)
printf("%d-%s\n",i,names[i]);
return 0;
}
int main(void)
{
const char* names[] = {"a","b","c", NULL}; /* Please note the additional, last element. */
ReadListOfName(names);
return 0;
}
The essential difference of this approach to the one passing two arguments discribing the list names[], is the fact that its use is less error-prone as the information of the list's size is drawn from the list itself, but from a second independently provided value.
you should pass an additional argument which will explicitly mention the length of the array. and where you are initializing setup some MACRO to fiddle with sizeofs.
sizeof(AnyPointer) gives word size. In case of 32-bit OS, 4 will be returned. similarly 8 will be returned in 64-bit machine.
So sizeof(char*) == sizeof(float*) == sizeof(int*) is true.
If your OS is 32-bit,
sizeof(names) will be 4.
sizeof(char*) also 4.
Obviously you will get len = 1.
This question already has answers here:
Determine size of dynamically allocated memory in C
(15 answers)
Closed 3 years ago.
I have faced some problem in this case can you please your ideas.
main()
{
char *p=NULL;
p=(char *)malloc(2000 * sizeof(char));
printf("size of p = %d\n",sizeof (p));
}
In this program Its print the 4 that (char *) value,but i need how many bytes allocated for
that.
You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes.
Here is one working example:
#include <stdlib.h>
#include <stdio.h>
void * my_malloc(size_t s)
{
size_t * ret = malloc(sizeof(size_t) + s);
*ret = s;
return &ret[1];
}
void my_free(void * ptr)
{
free( (size_t*)ptr - 1);
}
size_t allocated_size(void * ptr)
{
return ((size_t*)ptr)[-1];
}
int main(int argc, const char ** argv) {
int * array = my_malloc(sizeof(int) * 3);
printf("%u\n", allocated_size(array));
my_free(array);
return 0;
}
The advantage of this method over a structure with size and pointer
struct pointer
{
size_t size;
void *p;
};
is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.
There is no portable way but for windows:
#include <stdio.h>
#include <malloc.h>
#if defined( _MSC_VER ) || defined( __int64 ) /* for VisualC++ or MinGW/gcc */
#define howmanybytes(ptr) ((unsigned long)_msize(ptr))
#else
#error no known way
#endif
int main()
{
char *x=malloc(1234);
printf( "%lu", howmanybytes(x) );
return 0;
}
Although it may be possible that some libraries allows you to determine the size of an allocated buffer, it wouldn't be a standard C function and you should be looking at your library's own documentations for this.
However, if there are many places that you need to know the size of your allocated memory, the cleanest way you could do it is to keep the size next to the pointer. That is:
struct pointer
{
size_t size;
void *p;
};
Then every time you malloc the pointer, you write down the size in the size field also. The problem with this method however is that you have to cast the pointer every time you use it. If you were in C++, I would have suggested using template classes. However, in this case also it's not hard, just create as many structs as the types you have. So for example
struct charPtr
{
size_t size;
char *p;
};
struct intPtr
{
size_t size;
int *p;
};
struct objectPtr
{
size_t size;
struct object *p;
};
Given similar names, once you define the pointer, you don't need extra effort (such as casting) to access the array. An example of usage is:
struct intPtr array;
array.p = malloc(1000 * sizeof *array.p);
array.size = array.p?1000:0;
...
for (i = 0; i < array.size; ++i)
printf("%s%d", i?" ":"", array.p[i]);
printf("\n");
It is impossible to know how much memory was allocated by just the pointer. doing sizeof (p) will get the size of the pointer variable p which it takes at compile time, and which is the size of the pointer. That is, the memory the pointer variable takes to store the pointer variable p. Inside p the starting address of the memory block is stored.
Once you allocate some memory with malloc it will return the starting address of the memory block, but the end of the block cannot be found from it, as there is no terminator for a block. You define the end of the block therefore you need to identify it by any means, so store it somewhere. Therefore you need to preserve the block length somewhere to know where the block which is pointed to by p ends.
Note: Although the memory allocation structure keeps track of allocated and unallocated blocks, therefore we can know the allocated memory block length from these structures, but these structures are not available to be used by the users, unless any library function provides them. Therefore a code using such feature is not portable (pointed by #Rudy Velthuis) . Therefore it is the best to keep track of the structure yourself.
You need to keep track of it in a variable if you want to know it for later:
char *p = NULL;
int sizeofp = 2000*sizeof(char);
p = (char *)malloc(sizeofp);
printf("size of p = %d\n",sizeofp);
You cannot use the sizeof in this case, since p is a pointer, not an array, but since you allocate it, you already know:
main()
{
size_t arr_size = 2000;
char *p=NULL;
p=malloc(arr_size * sizeof(char));
printf("size of p = %d\n",arr_size);
}
Edit - If the malloc fails to allocate the size you wanted, it won't give you a pointer to a smaller buffer, but it will return NULL.
What do I need to change here so that animal contains {3,4}?
void funct(unsigned char *elf)
{
unsigned char fish[2]={3,4};
elf=fish;
}
int main()
{
unsigned char animal[2]={1,2};
funct(animal);
return 0;
}
EDIT: I see memcpy is an option. Is there another way just manipulating pointers?
Is there another way just manipulating pointers?
No, because animal is not a pointer. animal is an array. When you pass it as an argument to the function, it decays to a pointer to its first element, just as if you had said &animal[0].
Even if you use a pointer and take a pointer to it in funct, it still won't work:
void funct(unsigned char** elf)
{
unsigned char fish[2] = { 3, 4 };
*elf = fish; // oh no!
}
int main()
{
unsigned char animal[2] = { 1, 2 };
unsigned char* animal_ptr = animal;
funct(&animal_ptr);
}
After the line marked "oh no!" the fish array ceases to exist; it goes away when funct returns because it is a local variable. You would have to make it static or allocate it dynamically on order for it to still exist after the function returns.
Even so, it's still not the same as what you want because it doesn't ever modify animal; it only modifies where animal_ptr points to.
If you have two arrays and you want to copy the contents of one array into the other, you need to use memcpy (or roll your own memcpy-like function that copies array elements in a loop or in sequence or however).
Since animal decays to a pointer when passed to a function, you can replace:
elf=fish;
with:
elf[0] = fish[0]; // or: *elf++ = fish[0]
elf[1] = fish[1]; // *elf = fish[1]
or, assuming they're the same size:
memcpy (elf, fish, sizeof (fish));
Post question edit:
EDIT: I see memcpy is an option. Is there another way just manipulating pointers?
There is no safe way to do this by manipulating the pointers if you mean changing the value of the pointer itself. If you pass in a pointer to a pointer, you can change it so that it points elsewhere but, if you point it at the fish array, you're going to get into trouble since that goes out of scope when you exit from funct().
You can use the pointer to transfer characters as per my first solution above (elf[n] array access is equivalent to *(elf+n) pointer access).
One option is to assign the elements individually:
void funct(unsigned char *elf){
elf[0] = 3;
elf[1] = 4;
}
Another option is to use memcpy (which requires including string.h):
void funct(unsigned char *elf){
unsigned char fish[2]={3,4};
memcpy(elf, fish, 2);
}
memcpy takes as parameters the destination, the source, and then the number of bytes to copy, in this case 2.
void funct(unsigned char *elf) {
unsigned char fish[2]={3,4}; // stack variable, will dissapear after the function is exited
// elf=fish; this one assigns to the local copy of elf, that will also dissapear when we return
memcpy(elf, fish, sizeof(fish)); // so we have to copy values
// careful though, because sizeof(fish) can be bigger than sizeof(elf)
}
To help deal with maintenance issues, you're probably better off making a function that returns the pointer you want, and then making sure you've really freed any memory from the original array first.
unsigned char * func()
{
unsigned char * fish = malloc( sizeof(unsigned char) * 2 );
fish[0] = 3;
fish[1] = 4;
return fish;
}
int main ( void )
{
unsigned char * animal = malloc( sizeof(unsigned char) * 2 );
animal[0] = 1;
animal[1] = 2;
free( animal );
animal = func();
}
Trying to reassign an array declared using the 'unsigned char animal[2]' syntax is asking for trouble because it's put the entire original array on the stack, and even if the compiler allowed you to do that, you'd end up with a chunk of unusable memory on the stack. I don't design programming languages, but that feels very wrong.