Chris Herrera
Chris Herrera

Reputation: 61

C - trying to make string lowercase, keep getting segfault, valgrind says bad permissions for mapped memory at address

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

Answers (3)

mah
mah

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

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

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

olegst
olegst

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

Related Questions