【问题标题】:C - trying to make string lowercase, keep getting segfault, valgrind says bad permissions for mapped memory at addressC - 尝试使字符串小写,不断出现段错误,valgrind 表示地址处映射内存的权限错误
【发布时间】:2016-01-24 22:11:42
【问题描述】:

这个功能给我带来了很多麻烦,我认为这会比原来更容易。

lowerString 应该接受一些 char * 使字符串中的所有字母小写并返回。

我已经阅读了尽可能多的帖子,并使用了解决方案中的代码来编写我的代码,但我无法让它工作。我从搜索引擎结果中检查了各种 valgrind 问题的答案,但我无法弄清楚出了什么问题。

我认为这可能是一些字符串文字问题,但我只使用 char*

来自标头函数.h

char * lowerString(char *str);

来自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;
}

在我从 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;
}

我编译: gcc -Wall -Werror -pedantic -std=c99 -g -o b b.c functions.c

标志是不可协商的 =/

使用 valgrind --leak-check=full --show-leak-kinds=all -v ./b 运行时的 Valgrind:

--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)

【问题讨论】:

  • 感谢您的参考。此代码将用于我必须接受 char* 并且必须将其设为小写的地方。尝试@mah 建议立即使用 strdup。

标签: c


【解决方案1】:

abc 都指向存储在可能只读内存中某处的字符串文字。 您不得修改它们。使用strdup*()(或您平台上的等价物)创建一个新的char[] 供它们驻留。

a = strdup("The cat in le Hat");

 ...

free(a);

【讨论】:

    【解决方案2】:

    为什么是阿托伊?

     *p = tolower(atoi(p));
    

    只需将字符转换为 int。

    参考这个例子: http://www.tutorialspoint.com/c_standard_library/c_function_tolower.htm

    【讨论】:

    • 我之前尝试过,但出现错误:从指针转换为不同大小的整数 [-Werror=pointer-to-int-cast] *p = tolower((int)p);我可能投错了,我对此很陌生,C 中的头等舱
    • 必须转换为unsigned char
    • 不,当程序试图写入只读内存时是不正确的。
    • 是 unsigned char 还是 unsigned char*? functions.c:303:16: 错误:从指针转换为不同大小的整数 [-Werror=pointer-to-int-cast] *p = tolower((unsigned char)p); ^ cc1:所有警告都被视为错误
    • @ChrisHerrera:您必须取消引用指针:tolower((unsigned char)*p)
    【解决方案3】:

    问题模式是:

    a = "The cat in le Hat";
    p = lowerString(a);
    

    这是一个问题,因为 a 指向的常量数据通常是只读的,但您的 lowerString() 函数想要写入它:

    *p = tolower(atoi(p)); // Since p points to read-only memory, you crash here. 
    

    但是,作为@cremno cmets...您需要取消引用p! *p = tolower(*p);

    您需要让a 指向可写内存或让您的函数返回一个新缓冲区。例如,您可以:

    a = strdup("The cat in le Hat");
    

    然后根据需要使用a。如果您采用这种方法,请意识到您刚刚分配了一个新缓冲区,当您完成它时必须释放它,free(a);

    【讨论】:

    • 由于隐式函数声明,无法让 strdup 工作。 std=c99 标志将其作为声明取出(花了几分钟才弄明白,抱歉) malloc 会一样吗?试图使用 strdupa
    • #include &lt;string.h&gt; 得到strdup()的原型。如果需要,您可以使用malloc() 分配空间,但随后您需要复制字符串数据,可能使用strcpy() (也需要string.h)。
    • 知道了。使用:char *p; p = malloc((strlen(str)+1)*(sizeof(char))); strcpy(p,str);
    • 完成后不要忘记free(p);,以免造成内存泄漏。
    • 感谢您的帮助,我如何接受答案? >.
    猜你喜欢
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    相关资源
    最近更新 更多