Reputation: 3626
I have a struct vector
that holds it's data in a double void pointer. The struct looks like this:
typedef struct vector {
void **data;
int capacity;
int size;
} vector;
I am trying to somewhat replicate the std::find
function in C++ to find items in the vector
that I have. I have done this by creating a function vector_find
:
int vector_find(vector* v, void *elem, __compar_fn_t cmp)
{
for (int i = 0; i < v->size - 1; i++)
{
if(cmp(v->data[i], elem) == 0)
{
return i;
}
}
return -1;
}
This function is found in my vector.c
file. It accepts a comparator function. If it finds the element, it will return its location in the vector.
This is all defined in my vector.c
file.
Now I am trying to use this function in one of my programs, in this function:
int cstring_cmp(const void *a, const void *b)
{
const char *ia = *(const char **)a;
const char *ib = *(const char **)b;
printf("%s %s", ia, ib);
return strcmp(ia, ib);
}
void
execute(vector* tokens)
{
if (vector_find(tokens, ";", cstring_cmp) > -1)
{
printf("semicolon found");
}
}
However, when I run this function, I get a segfault with the following error:
Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:120
120 ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory.
A couple of things I have verified:
I have verified that the error occurs in my execute
function. Specifically when I call vector_find.
I have verified that this error comes up whether or not tokens
is empty. This is interesting because the for-loop in vector_find
should never execute if the vector I pass to vector_find
is empty.
I have included in both vector.c
and the file I am running.
I have also tried this format:
int vector_find(vector* v, void *elem, int (*cmp) (const void*, const void*))
{
for (int i = 0; i < v->size; i++)
{
if((*cmp) (v->data[i], elem) == 0)
{
return i;
}
}
return -1;
}
...and got the same error.
Am I doing this right? Obviously not - where does my error lie?
Upvotes: 2
Views: 82
Reputation: 223739
Your comparison function is expecting that each of its parameters is a char **
. However, you call vector_find
with a char *
being passed as the second parameter which is subsequently passed to cmp
. Attempting to use a char *
as a char **
invokes undefined behavior as you end up passing to strcmp
is actually a char
.
You don't show how you populate your vector
, but I'm guessing the elements of data
are of type char *
. That being the case, the comparison function should be expecting a char *
instead of a char **
.
int cstring_cmp(const void *a, const void *b)
{
const char *ia = a;
const char *ib = b;
printf("%s %s", ia, ib);
return strcmp(ia, ib);
}
Upvotes: 1
Reputation: 385144
If I'm reading this right, you've written a comparator that pretends a vector
is a const char*
. It isn't. The subsequent C-string comparison is likely not to hit a would-be null terminator and is going to go out of bounds.
Instead, write a comparator that actually compares vector
objects to whatever it is that you want to compare them to.
Upvotes: 0