Reputation: 61
This function has been giving me a lot of trouble and I thought this would be easier than it's turned out.
lowerString is supposed to take in a some char * make all letters in the string lowercase and return that.
I've read as many posts as I can find and used code from solutions to write my code but I can't get it to work. I checked all sorts of answers from valgrind issues from search engine results but I can't figure out what's going wrong.
I thought it might be some string literal issue but I only use char*
From header functions.h
char * lowerString(char *str);
From functions.c:
/* Makes everything in the string lowercase */
char * lowerString(char *str){
char *p;
p = str;
for( ; *p; ++p){
*p = tolower(atoi(p));
}
return p;
}
In code I'm running from b.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "functions.h"
int main(void){
char *a, *b, *c, *p;
a = "The cat in le Hat";
b = "Meow meow meow meow";
c = "This an$example12 mail@rutgers";
p = lowerString(a);
printf("%s\n",p);
p = lowerString(b);
printf("%s\n",p);
p = lowerString(c);
printf("%s\n",p);
return 0;
}
I compile with: gcc -Wall -Werror -pedantic -std=c99 -g -o b b.c functions.c
Flags are non-negotiable =/
Valgrind when run with valgrind --leak-check=full --show-leak-kinds=all -v ./b:
--6277-- REDIR: 0x4019ca0 (strlen) redirected to 0x38068331 (???)
--6277-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--6277-- Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so ..
--6277-- .. CRC mismatch (computed 329d6860 wanted c0186920)
--6277-- object doesn't have a symbol table
--6277-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so
--6277-- Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so ..
--6277-- .. CRC mismatch (computed 1fb85af8 wanted 2e9e3c16)
--6277-- object doesn't have a symbol table
==6277== WARNING: new redirection conflicts with existing -- ignoring it
--6277-- old: 0x04019ca0 (strlen ) R-> (0000.0) 0x38068331 ???
--6277-- new: 0x04019ca0 (strlen ) R-> (2007.0) 0x04c2e1a0 strlen
--6277-- REDIR: 0x4019a50 (index) redirected to 0x4c2dd50 (index)
--6277-- REDIR: 0x4019c70 (strcmp) redirected to 0x4c2f2f0 (strcmp)
--6277-- REDIR: 0x401a9c0 (mempcpy) redirected to 0x4c31da0 (mempcpy)
--6277-- Reading syms from /lib/x86_64-linux-gnu/libc-2.19.so
--6277-- Considering /lib/x86_64-linux-gnu/libc-2.19.so ..
--6277-- .. CRC mismatch (computed dc620abc wanted 148cbd6e)
--6277-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so ..
--6277-- .. CRC is valid
--6277-- REDIR: 0x4ec3d60 (strcasecmp) redirected to 0x4a25720 (_vgnU_ifunc_wrapper)
--6277-- REDIR: 0x4ec6050 (strncasecmp) redirected to 0x4a25720 (_vgnU_ifunc_wrapper)
--6277-- REDIR: 0x4ec3530 (memcpy@GLIBC_2.2.5) redirected to 0x4a25720 (_vgnU_ifunc_wrapper)
--6277-- REDIR: 0x4ec17c0 (rindex) redirected to 0x4c2da30 (rindex)
==6277==
==6277== Process terminating with default action of signal 11 (SIGSEGV)
==6277== Bad permissions for mapped region at address 0x401C68
==6277== at 0x401A02: lowerString (functions.c:303)
==6277== by 0x400D08: main (b.c:13)
--6277-- REDIR: 0x4eb9df0 (free) redirected to 0x4c2bd80 (free)
==6277==
==6277== HEAP SUMMARY:
==6277== in use at exit: 0 bytes in 0 blocks
==6277== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==6277==
==6277== All heap blocks were freed -- no leaks are possible
==6277==
==6277== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==6277== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Upvotes: 0
Views: 246
Reputation: 39827
The problem pattern is:
a = "The cat in le Hat";
p = lowerString(a);
This is a problem because a
points to constant data which is typically going to be read-only, but your lowerString()
function wants to write into it:
*p = tolower(atoi(p)); // Since p points to read-only memory, you crash here.
However, as @cremno comments... you need to dereference p! *p = tolower(*p);
You need to either make a
point to writable memory or make your function return a new buffer. For example, you might:
a = strdup("The cat in le Hat");
Then use a
as you need. If you take this approach, realize you've just allocated a new buffer that you must release when you are done with it, with free(a);
.
Upvotes: 1
Reputation: 799110
a
, b
, and c
all point to string literals stored somewhere in potentially read-only memory. You must not modify them. Use strdup*()
(or their equivalents on your platform) to create a new char[]
for them to reside in.
a = strdup("The cat in le Hat");
...
free(a);
Upvotes: 3
Reputation: 1267
Why atoi?
*p = tolower(atoi(p));
Just cast character to int.
Refer to this example: http://www.tutorialspoint.com/c_standard_library/c_function_tolower.htm
Upvotes: 2