Trying to follow this example. (Section String sorting...)
Is there anything obvious that would make this crash in stdlib's qsort.c?
I also tried cstring_cmp with strncmp specifying 30 chars max, much more than I have.
*fileArray[20] seems to be correctly populated with strings.
Thanks.
char* ptr_fileName;
char* fileArray[20];//number of files
size_t strings_len;
ptr_fileName = (char*)malloc((strlen(FindFileData.cFileName)+1)*sizeof(char));
memcpy(ptr_fileName, FindFileData.cFileName, strlen(FindFileData.cFileName)+1);
fileArray[i] = ptr_fileName;
strings_len = sizeof(fileArray) / sizeof(char *);
qsort(fileArray, strings_len, sizeof(char *), cstring_cmp);
//crashing in qsort.c
qsort c-string compare function:
/* qsort C-string comparison function */
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
/* strcmp functions works exactly as expected from
comparison function */
}
You say you are only filling fileArray with 10 strings, leaving 10 entries uninitialized.
When you call qsort, you pass 20 as the strings_len argument.
This will, of course, result in undefined behavior.
You have to give qsort accurate information.
If you are passing 10 strings in the array, you must also pass the number 10 as the number of elements to be sorted.
Note:
If you follow my earlier answer, setting a breakpoint on cstring_cmp, you would quickly see when the compare method is called with invalid data, leading directly to the crash.
How do you populate:
char* fileArray[20];
as it stands, it's an array of uninitialised pointers.
Set a breakpoint in cstring_cmp, and watch as it is called each time.
See if the ultimate crash happens inside cstring_cmp, or in qsort.
Check the state of the fileArray just before the crash.
*fileArray[20] seems to be correctly populated with strings.
The asterisk before fileArray makes me veeeery suspicious about the correctness of the way you populated the array.
I don't observe anything else that might break your code.
As you are not initialising the contents of fileArray, it legal contains random memory, not legal char pointers.
Related
I have an array of pointers to string:
char *TAB[3] = { "dafafa", "alfkasf", "bafgr" };
I would like to sort characters in in each of those strings.
My compare function:
int cmp(const void *a, const void *b)
{
return *(char *)a - *(char *)b;
}
and while trying qsort on one of these:
qsort(TAB[0], 6, sizeof(char), cmp);
The program doesn't work.
After many efforts I found that the reason of the problem is in delivering TAB[0] to qsort().
Can anyone explain why it doesn't work and how to fix that?
If you want to sort characters inside each string, the first thing you must ensure is that your strings can be written to. As it currently stands, your strings are read-only, so you cannot sort their characters without copying their content into memory that allows writing.
Next thing is that you need a loop. Since you are sorting each string individually, you need to loop through the array, and call qsort on each item. The initial item is TAB[i], and the length is strlen(TAB[i]). Your cmp function will work.
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 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}
I get a segfault when trying to memset an array of chars that was allocated statically, but not for an array of the same length that was allocated using malloc.
variable definitions:
//static
char inBuff[IN_BUFF_LEN];
//dynamic
char * inBuffD;
function call:
//static, cast used because char** != char (*) [n]
serverInit(portNum, (char**) &inBuff, &serv_addr, &sockfd)
//dynamic
serverInit(portNum, &inBuffD, &serv_addr, &sockfd)
use within the function:
memset(*inBuffAdr, 0, IN_BUFF_LEN);
I suspect that my problem is in the difference of the function calls, or to be more precise, my incomplete understanding of the "char** != char (*) [n]" situation. But I have been banging at this for too long and can't see the forest from the trees so any hints and advice would be very appreciated.
Just send inBuff (not **inBuff) and then memset inBuffAdr and not *inBufAdr (your other memset is probably not working either, you just don't know it yet)
Why do you need to pass a double-pointer to your serverInit() function? If the function can modify where the pointer points to, then you can't pass a statically allocated array. If the function can't modify where the pointer points to, then you don't need a double-pointer.
The type of &inBuff is pointer to array of char of size IN_BUFF_LEN, which is quite distinct from a char **. You've bludgeoned the compiler into not complaining, claiming that you know better than the compiler what you're doing. Don't use a cast like that unless you are sure you do know more than the compiler.
Frankly, given the current prototype, you'd probably be best off with:
//static
char inBuff[IN_BUFF_LEN];
char *inBuffS = inBuff;
//dynamic
char *inBuffD;
serverInit(portNum, &inBuffS, &serv_addr, &sockfd);
However, I'm deeply suspicious that you should revise serverInit() to take a simple char * instead of char ** for the second argument.
Why not define serverInit() the following way:
serverInit(...., char * inBuff, ....)
then call it
serverInit(...., inBuff, ....)
and then inside serverInit() call memset() like this:
memset(inBuff, 0, IN_BUFF_LEN);
Part of your confusion is in thinking that &inBuff can be dereferenced to get inBuff. If you run this simple test program:
#include <stdio.h>
char inBuff[1000];
int main( int argc, char *argv[])
{
printf( "%p %p\n", inBuff, &inBuff);
return 0;
}
You'll see that it prints the same address for both notations. If you try to dereference &inBuff, you'll be taking the first few bytes of the array as an address.
As others have stated, you should just be passing a pointer to the memory you're going to set. Hopefully this answer will help you with future debugging sessions.
I have a variable 'jmp_code' that is declared as a char *. When I run the following commands
printf("char by char, the code is '%c%c%c%c'\n", *jmp_code, *(jmp_code+1), *(jmp_code+2),*(jmp_code+3));
printf("printing the string, the code is '%s'\n", jmp_code);
I get the following results
char by char, the code is '0,0,0, ,'
printing the string, the code is 'ö\├w≡F┴w'
I am using codeblocks. Here is the sample code I am playing with.
#include <stdio.h>
#include <string.h>
char * some_func(char * code);
char * some_func(char * code) {
char char_array[4];
strcpy(char_array, "000");
code = char_array;
return code;
}
int main ( void ) {
char * jmp_code = NULL;
jmp_code = some_func(jmp_code);
printf("char by char, the code is '%c,%c,%c,%c,'\n", *jmp_code, *(jmp_code+1), *(jmp_code+2),*(jmp_code+3));
printf("printing the string, the code is '%s'\n", jmp_code);
return 0;
}
I am quite confused by this. Any help would be appreciated.
Thanks
Some quick observations:
char * some_func(char * code) {
char char_array[4];
strcpy(char_array, "000");
code = char_array;
return code;
}
You can't assign strings using = in C. That messes things up - you're assigning code the pointer of your locally allocated char_array to code, but you're not copying the contents of the memory. Also note that since char_array is allocated on the stack (usually), you'll find it disappears when you return from that function. You could work around that with the static keyword, but I don't think that's the nicest of solutions here. You should use something along the lines of (big warning this example is not massively secure, you do need to check string lengths, but for the sake of brevity):
void some_func(char * code) {
strcpy(code, "000");
return;
}
(Refer to this (and this) for secure string handling advice).
And call it via some_func(jmp_code) in main. If you're not sure what this does, read up on pointers.
Second problem.
char * jmp_code = NULL;
Currently, you've declared space enough for a pointer to a char type. If you want to use my suggestion above, you'll need either to use malloc() and free() or else declare char jmp_code[4] instead, such that the space is allocated.
What do I think's happening? Well, on my system, I'm getting:
and the code is '0,0,0,,' and the code
is ''
But I think it's chance that jmp_code points to the zeros on the stack provided by your some_func function. I think on your system that data has been overwritten.
Instead you're reading information that your terminal interprets as said character. Have a read of character encoding. I particularly recommend starting with The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
You're returning a reference to a temporary array. char_array goes away when some_func() retuns, but you keep using the address of it. You need to use malloc() to allocate an array and then free() it after you use it.
You're printing from an invalid pointer. char_array is on the stack of some_func() function.
The function returns the pointer of something that is on the stack and will be no more after the function returns!
The first printf finds the stack still unchanged, the second, maybe, found it filled with... garbage!
It might be interesting to see:
const char *pos = jmp_code;
while (*pos)
printf("%d ", *pos++);
I think char type can not use non-ascii char codes. Meaning your string contains UTF-8 or like symbols which code could be in (0, over9000) range, while char codes could be in (0, 255) range.
I'm trying to convert some code from a dynamic-typed language to C. Please
bear with me as I have no practical experience yet with C.
I have a dispatcher function that decides how to convert it's input based on
the value of the flag argument.
void output_dispatcher(char *str, int strlen, int flag) {
char output[501];
char *result;
switch (flag) {
/* No conversion */
case 0:
result = str;
break;
case 1:
result = convert_type1(output, str, strlen);
len = strlen(result);
break;
/* ... */
}
/* do something with result */
}
I currently have 5 different output converters and they all (even future
ones) are guaranteed to only produce 300-500 characters. From my reading, it
is preferable to use a heap variable than dynamically allocate space on the
stack, if possible. The function declaration for one looks like:
static char * convert_type1(char *out, const char *in, int inlen);
I want to avoid the strlen in the dispatcher, since it is uncessary to
recalculate the output size because the output converters know it when they
construct the output. Also, since I'm passing in a pointer to the output
variable, I shouldn't need to return the result pointer, right? So I modify
it to the following, but get an 'incompatible type' compilation error.
void output_dispatcher(char *str, int strlen, int flag) {
char output[501];
switch (flag) {
/* No conversion */
case 0:
output = str; /* ERROR: incompatible type */
break;
case 1:
strlen = convert_type1(output, str, strlen);
break;
/* ... */
}
/* do something with result */
}
Can this approach work, or is there a better way to go?
To avoid the recalculation your output converters would need to have a prototype like this:
static char * convert_type1(char *out, const char *in, int *len);
called thus:
result = convert_type1(output, str, &strlen);
Internally the output converter would need to read the contents of the pointer now containing the string length, and overwrite the contents of that pointer before returning.
On the issue of heap vs stack, indeed you need to use the heap since variables allocated on the stack will disappear as soon as the function ends.
The line:
output = str;
is giving you problems because, while arrays and pointers are similar, they're not the same.
"output" is an array, not a pointer.
str = output;
will work, because a char ptr is much like an array variable.
But the opposite does not because the "output" variable is not just the pointer to the array, but the array itself.
For example, if you had:
char output[501];
char output1[501];
and you did:
output1 = output;
This would be ok, and C would copy the contents of the output array in to the output1 array.
So, you're just a little confused about arrays and ptrs.
char output[501];
output = str; /* ERROR: incompatible type */
=>
strncpy(output, str, sizeof(output));
Note, you should check if 'output' is big enough to hold 'str'
The error in this case makes sense. output is a buffer that will hold come char data, while str is a pointer to some other area in memory. You don't want to assign the address of what str is pointing to output, right? If you want to go with this approach I think would just copy the data pointed to by str into output. Better yet just use str if no conversion is required.
C does not allow arrays to be modified by direct assignment - you must individually modify the array members. Thus, if you want to copy the string pointed to by str into the array output, you must use:
strcpy(output, str);
or perhaps
memcpy(output, str, strlen + 1);
(In both cases, after first checking that strlen < sizeof output).
Note that naming a local variable strlen, thus shadowing the standard function of that name, is going to more than a little confusing for someone who looks at your code later. I'd pick another name.