what's wrong with my clean function? - c

I want to write a function clearing any string from numbers and signs like !##$%^&*()_+ but always I get this error: * glibc detected ./clear: invalid fastbin entry (free): 0x0000000001d29490 **
Here's the code:
void clean(char *dirty)
{
int i = 0, j = 0;
char *temp;
temp = strdup(dirty);
while(i < strlen(temp))
{
if(isalpha(temp[i]) && isspace(temp[i]))
{
dirty[j] = temp[i];
j++;
}
i++;
}
dirty[j] = '\0';
free(temp);
}

You should check for the return value of strdup. If the memory allocation encountered problems (e.g. not enough memory), temp gets the value NULL. Check if that is the case and exit with an error message.
Your if statement is always false:
if(isalpha(temp[i]) && isspace(temp[i]))
How could temp[i] be both alphanumerical and space?
Note also (although it's not the question) that this is rather a job for for than while (looping through all elements of an array until its end). It's always good to use the expected idiom.
This could also be done in place (no need for a temp string):
dirty[j] = dirty[i];
since i is greater or equal to j.

There could be several reasons causing the OP's code to crash:
1 strdup() returned NULL.
Test its result:
char * temp = strdup();
if (NULL == temp)
{
perror("strdup()" failed");
return;
}
2 On a 64bit system: strdup()'s prototype is missing
Include the appropriate header and, as it's not a standrd C, function make sure it is defined in there:
#define _POSIX_C_SOURCE 200809L /* or greater */ /* for gcc us option -std=c99 */
#include <string.h>
As per lulyon's comment: For various other possibe #define enabling strdup() protoyping please read here.
3 The string passed to clean(char * dirty) is NULL
Perform input validation:
if (NULL == dirty)
{
perror("invalid input");
return;
}
4 The string passed to clean(char * dirty) referrs to an unmutable constant
Do not call clean
like this:
char * dirty = "*ç%&/*alk 42";
clean(dirty);
neither like this:
clean("*ç%&/*alk 42");
nor like this:
#define dirty "*ç%&/*alk 42"
clean(dirty);
5 (As per Mike Hartl's comment) The string passed to clean(char * dirty) is missing its 0-termination
Undetectable from inside clean(), so fix the input.

if(isalpha(temp[i]) && isspace(temp[i])) // logic AND. The character could not be both alpha and space
should be
if(isalpha(temp[i]) || isspace(temp[i])) // logic OR.
The remaining part of code is of no problem.
Update:
The code works fine on my Window PC. So here I can only recommend checking errno to find what is wrong.
One more thing, check the pointer char *dirty and char *temp if they are empty before using them.
Update:
a useful link that explains strdup: Strdup returning address out of bounds

The logic of your loop seems to be flawed. This will never hold
isalpha(temp[i]) && isspace(temp[i])
so j will always be 0 at the end.

If you work under linux, You may consider valgrind usage for memory problems detection

Related

malloc() into a recursive function that modifies a string

THE CODE:
The aim of this code is to take a string of 0 1 and * and print all the combinations of strings obtained replacing * with 0 or 1.
Ex.
input : 0*1 => output: 001 011
the idea is to build a recursive function (for practice purposes):
void rec_print (char *mod_str)
which counts the occurrences of *, the offset of the first * encountered while looping the string (I have used ternary just to practice them)
for(int i=0; mod_str[i]; i++) {
n_star = (mod_str[i] == '*') ? n_star+1 : n_star;
if (offset==-1) {
offset = (mod_str[i] == '*') ? i : -1;
}
}
The base case occurs when there is only one *, in which case replaces * with 0, prints the string, replace the 0 with a 1, and finally prints the string:
if (n_star==1) {
mod_str[offset] = "0";
printf("\n%s", mod_str);
mod_str[offset] = "1";
printf("\n%s", mod_str);
}
otherwise modifies the first * of the string to a 0 then call itself, then modify it to a 1 when it comes back, and finally call itself:
else {
// replace the first encountered * to 0 and recall itself
mod_str[offset] = "0";
rec_print(mod_str);
// replace the previous 0 to 1 and recall itself
mod_str[offset] = "1";
rec_print(mod_str);
}
THE ISSUE:
as you will notice here the problem is that I am trying to modify a string which memory is read-only (yes, I have a huge "Python bias" here), normally I would use a malloc() to resolve this but I can't figure out how to use it inside a function to modify a string.
I am well aware recursion is not the best solution to this exercise but I need to satisfy my curiosity about this.
I thank everyone for the time spent here and apologize for my eventual English mistakes in advance.
The base case occurs when there is only one *, in which case replaces * with 0, prints the string, replace the 0 with a 1, and finally prints the string:
This base case isn't really "base." For example, you could receive the string "001" as input, which contains zero stars. You should modify your base case to handle only zero stars, and rely on your recursive case to simplify the case with one star to zero stars.
as you will notice here the problem is that I am trying to modify a string which memory is read-only
If the memory is read-only, you should clarify that fact to the compiler! Then the compiler can check your code to make sure it never writes to a read-only variable.
Example:
void rec_print (const char *mod_str)
as you will notice here the problem is that I am trying to modify a string which memory is read-only (yes, I have a huge "Python bias" here), normally I would use a malloc() to resolve this but I can't figure out how to use it inside a function to modify a string.
You need to copy the string to a place where you can modify it. Here's an example:
void rec_print (const char *src_str) { // note name change
// Allocate memory
char *mod_str = malloc((strlen(src_str) + 1) * sizeof(char));
// This function copies src_str to mod_str
strcpy(mod_str, src_str);
// Rest of function
...
// Clean up memory used
free(mod_str);
}
Here we allocate enough memory to hold the input string. Then, we copy the input string to the space we allocated. We can do all modifications on this copy. At the end we free the allocation.

Find substring in a string

Here is my code to find substring entered by the user in the given string.
bool find_str(char *str, char const *substr) {
while(*str) {
if(*str++ == *substr) {
char const *a = substr;
while((*str++ == *++a)); /*empty*/
if(*a == '\0')
return true;
}
}
return false;
}
// If match found, then return true, else false
int main(void) {
printf("%d", find_str("ABCDEF", "CDE")); /* Return true in this case */
printf("%d", find_str("ABCDE", "CDE")); /* Return false in this case */
}
As explained in the comment, it returns true whenever it ends with an additional characters. If it is not, then it returns false. I think there is a problem in increment/decrement operator. But I could not find how?
This is because your code decides to stop on finding \0 only after performing the comparison
*str++ == *++a
This condition will be true even when the match happens at the end of the string on null terminators, so the while loop would happily proceed beyond the end of both strings past the null terminator, causing undefined behavior.
Changing the condition to exit when *a is zero should fix the problem:
while((*str++ == *++a) && (*a));
I analysed you piece of code a little bit and based on my analysis,
I think the problem is in here
while((*str++ == *++a)); /*empty*/
perhaps you would like to add another statement like below
while((*str++ == *++a) && ( *a != '\0' ) ) ; /*empty*/
I guess you are missing a null check, what if both pointer are pointing to NULL termination they will still go forward that's exactly whats happening
I was going through your piece of code and found quite a few interesting things
Lets say the memory allocated for CDE is at X
say again the memory allocated for ABCDEF is at X+4 (this was the case in my machine)
and say memory block allocated for ABCDE is at some X+Y or what ever
now when the function is called second time
both pointers a and str point to respective memory locations starting at X+2 where Character C satisfies the condition above, however the condition will still be true even if they reach to end i.e at X+3 and hence a will move forward and point to A which makes your program behave erroneously

STM32 printf and RTC

* UPDATE *
Here is what I found. Whenever I had that function in there it wouldn't actually make the code lock up. It would actually make the read RTC I²C function very slow to execute, but the code would still run properly, but I had to wait a really long time to get past every time I read the RTC.
So there is an alarm interrupt for the RTC and this was triggering other I²C interactions inside the ISR, so it looks like it was trying to do two I²C communications at the same time, therefore slowing down the process. I removed the functions in the ISR and it's working now. I will keep investigating.
I am having this problem when programming an STM32F103 microcontroller using IAR 5.40. I have this function that if I try to printf a local variable it causes the code to freeze at another point way before it even gets to that function in question.
What could possibly be causing this?
This is the function:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[3] = {0};
itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string
printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
I tried this as well and this does not cause the lock I experienced:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[3] = {0};
itoa(bSmsIndex, bTmpSms, 10);
printf("index = 2\n");
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
There is no optimization enabled whatsoever and the code gets stuck when trying to read a byte out of my I²C RTC, but as soon as I remove this printf("index = %s\n", bTmpSms); or use this one instead printf("index = 2\n"); then everything is happy. Any ideas?
The bSmsIndex will never be more than 30 actually and even then the lock up happens wayyyy before this function gets called.
char bTmpSms[3] only has space for "99". If your bSmsIndex is 100 or greater, you will be trying to write to memory that doesn't belong to you.
Edit after the update
I don't have a reference to itoa on my local machine, but I found this one ( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ ). According to that reference, the destination array MUST BE LONG ENOUGH FOR ANY POSSIBLE VALUE. Check your documentation: your specific itoa might be different.
Or use sprintf, snprintf, or some function described by the Standard.
Some ideas:
If itoa() is not properly NUL-terminating the string, then the call to printf may result in the machine looking for the NUL forever.
pmg has a very good point.
Also, consider what type the first argument to itoa() is. If it's signed and you're passing in an unsigned integer, then you may be getting an unexpected minus sign in bTmpSms. Try using sprintf() instead.
The change in code is moving the rest of your code around in memory. My guess is that some other part of the code, not listed here, is bashing some random location; in the first case that location contains something critical, in the second case it does not.
These are the worst kinds of problems to track down*. Good luck.
*Maybe not the worst - it could be worse if it were a race condition between multiple threads that only manifested itself once a week. Still not my favorite kind of bug.
It seems that if I don't initialize the variable bTmpSms to something the problem occurs.
I also realized that it is not the printf that is the problem. It is the itoa function. It got me to check that even though I didn't think that was the problem, when I commented the itoa function then the whole code worked.
So I ended up doing this:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[4] = "aaa"; // I still need to find out why this is !!!
itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string
printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
This is the itoa function I got:
char itoa(int value, char* result, int base)
{
// Check that the base if valid
if (base < 2 || base > 36) {
*result = '\0';
return 0;
}
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do
{
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsr
qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while (value);
// Apply negative sign
if (tmp_value < 0)
*ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr)
{
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return 1;
}
What's the value of bSmsIndex you're trying to print?
If it's greater than 99 then you're overrunning the bTmpSms array.
If that doesn't help, then use IAR's pretty good debugger - I'd drop into the assembly window at the point where printf() is being called and single step until things went into the weeds. That'll probably make clear what the problem is.
Or as a quick-n-dirty troubleshoot, try sizing the array to something large (maybe 8) and see what happens.
What's the value of bSmsIndex?
If more than 99 it will be three digits when converted to a string. When zero terminated, it will be four characters, but you've allocated only three to bTmpSms so the null may get overwritten and the printf will try to print whatever is after bTmpSms until the next null. That could access anything, really.
Try to disassemble this area with index = 2 vs. index = %s.

Memory issue in my Sub String function in C?

I have this C function which attempts to tell me if a sub string is contained in a string.
int sub_string(char parent [1000], char child [1000]){
int i;
i = 0;
int parent_size = (int) strlen(parent);
int child_size = (int) strlen(child);
char tempvar [child_size];
int res;
res = 1;
while(i<(parent_size - child_size + 1) && res != 0){
strncpy(tempvar, parent + i, child_size);
if(strcmp(tempvar, child)==0){
res = 0;
}
i++;
memset(tempvar, 0, child_size);
}
memset(tempvar, 0, sizeof(tempvar));
return res;
}
Now the strange thing is, when I pass a string "HOME_DIR=/tmp/" and "HOME_DIR" it returns a 0 the first time round, but after I call this function again, it returns a 1 to say it hasn't found it!!
I am guessing this is a memory issue, but I can't tell where, I would appreciate any help on this.
Is there any reason you can't use the strstr function? Otherwise there are some things you should clean up in your code. For starters since you are limiting the length of the arrays coming in to 1000 characters you should use strnlen instead of strlen with a limit of 1000. You should also create you should zero out the tempvar array before you start copying into it. If parent is not null terminated you could run off the end of the array in your while loop. I would also suggest using strncmp and giving a length limit (in general if you are using the C string library you should use the 'n' version of the functions i.e. strnlen instead of strlen so that you put a bounding length on the operation, this helps to protect buffer overflows and potential security holes in your code).
I have noticed some issues with this program:
Use pointers instead of fixed char arrays. This is more space optimal. So your function definition becomes int sub_string(char *parent, int parent_len, char *child, int child_len). Please note that since I pass pointers I also need to pass the length of the string so I know how much to traverse. So now you access your string like so *(parent+i) in a loop.
i<(parent_size - child_size + 1) This condition looks a bit dicey to me. Let's say parent is 100 in len & child is 75. so this expression becomes i<26. Now your loop will terminate when i>26. So tempvar would have the parent_string till index 25. So how does this work again?
One problem is:
char tempvar [child_size];
strcmp below will compare child_size+1 characters (incl. terminating '\0'), therefore its undefined behaviour.
Do you know the C-standard functions strstr and strncmp?
sizeof(tempvar) does not return child_size.

Explanation of stack overflow when using read on a small file and a questionable workaround

I hope the question explained my problem. I would also be grateful if the workaround that "works" is explained.
The traditional way of reading a file (that i know of)
int fd;
char buffer[MAX];
while(read(fd,buffer,MAX)>0)
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
was causing an overflow. The workaround that somehow unexpectedly worked was
while((read(fd,buffer,MAX)!=0)||(read(fd,buffer,MAX)!= -1))
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
^^ This code printed out the entire file, no skips as far as observable.
Things like
do
{
int temp;
temp=read(fd,buffer,MAX);
if((temp == 0) || (temp == -1))
{
break;
}
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}while(1);
also caused a stack overflow. Am i missing something really important here?
Thanks
Why do you say that it's causing an overflow?
Do note that read() will not write a \0 in the end of the char array, so if you do something like printf("%s", buffer) it will likely fail because printf will be expecting a NUL terminated string. You may be wanting to read MAX-1 and set buffer[number_of_read_characters] = '\0' where number_of_read_characters is whatever read() returned, if positive.
Also note that when you declare char buffer[MAX], since in C indexing is zero-based, the highest buffer index is MAX-1, so when you're setting buffer[MAX]='\0' you're already out of your array bounds.
One problem:
buffer[MAX]='\0';
steps on stack, as the highest valid index for array of size MAX is MAX-1 (due to 0-based indexes).
-1 return value from read indicates an error, so the right thing to test read() > 0. Moreover, the normal return value from read is the number of bytes read, and read does not guarantee any 0-termination. you have to do someting along the lines of
while (bytesRead=read() > 0) {
write(buffer, bytesRead);
...
Glancing at the code, I'd suggest that it's because the logic is different.
In the example that works, the read(fd,buffer,MAX) method is being executed twice.
Think of it like:
while (dosomething() != 0 || dosomething() != -1)
{
// some work
}
This loop will be infinite if the dosomething() method is idempotent, however if the first time you run it within the while statement is different than the second, it will break.
That explains how the execution path differs, but I can't figure out why the first option overflows... I'll think about it and update. (or not - it seems it's been answered!)
Try this:
int fd, readCharacter;
char buffer[MAX];
while( readCharacter = read(fd, buffer, MAX**-1**) > 0 )
{
buffer[readCharacter] = '\0';
// ...
}

Resources