C:错误分配指针[重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C:错误分配指针[重复]相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
我有一个char数组,我想删除单词(或短语)之前或之后的空白,而不是中间。
例如:
“你好” - >“你好”
“你好” - >“你好”
“你好” - >“你好”
" " --> ""
这是我的代码:
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s[] = " prova ";
char *t = NULL;
if (s == NULL)
{
t = NULL;
}
else {
int n = strlen(s);
t = malloc(sizeof(char)* (n + 1));
for (int i = 0; i <= n; ++i)
{
t[i] = s[i];
}
int k = 0;
if (s[0] == ' ')
{
++k;
t = realloc(t, sizeof(char)*n);
for (int i = 0; i <= n - 1; ++i)
{
t[i] = s[i + 1];
}
}
if (s[n - 1] == ' ')
{
if (k == 1)
{
int j = 0;
t = realloc(t, sizeof(char)*(n - 1));
for (int i = 0; i <= n - 2; ++i)
{
t[i] = t[i];
j = i;
}
t[j] = 0;
}
else
{
int j = 0;
t = realloc(t, sizeof(char)*n);
for (int i = 0; i <= n - 1; ++i)
{
t[i] = t[i];
j = i;
}
t[j] = 0;
}
}
}
return t;
}
调试不会给我错误或其他东西,但我知道内存和堆有问题,我不知道如何删除它。
我在这个平台上寻找与我类似的其他问题并且它们存在,但没有一个答案解决了我的问题。
请给我一些建议,谢谢
答案
从以下开始,代码中存在大量小错误:
if (s == NULL)
s
永远不会是NULL
,除非您的编译器完全损坏或者您的堆栈少于8字节。
接下来,在删除前导空格之前,您需要realloc
,例如
t = realloc(t, sizeof(char)*n);
for (int i = 0; i <= n - 1; ++i)
未指定调用realloc
截断哪些(如果有)字节。相反,你需要在调用t
之前对realloc
进行操作以删除前导空格(然后你仍然不能保证任何内存都会被调整)
接下来,你多次调用realloc
,当你应该简单地操作s
中t
的原始副本来删除前导/尾随空格,然后在最后调用realloc
。从效率的角度来看,malloc/realloc
是相对昂贵的电话,不应该重复调用。
重新排列逻辑,您可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s[] = " prova ";
char *t = NULL;
size_t n = strlen(s); /* strlen returns size_t */
int k = 0;
t = malloc (n + 1); /* sizeof(char) is 1 */
if (t == NULL) { /* validate ALL allocations */
perror ("malloc-t");
return 1;
}
for (size_t i = 0; i <= n; i++) /* copy s to t */
t[i] = s[i];
while (t[k] == ' ') /* count leading whitespace */
k++;
for (size_t i = 0, j = k; j <= n; i++, j++) /* remove whitespace */
t[i] = t[j];
n -= k; /* update n */
while (n && t[n - 1] == ' ') /* remove trailing whitespace */
t[n-- - 1] = 0;
void *tmp = realloc (t, n + 1); /* realloc with tmp varaible */
if (tmp == NULL) { /* validate ALL allocations */
perror ("realloc-t");
return 1;
}
t = tmp; /* assign new block to t */
printf ("t: '%s'
", t);
free (t); /* don't forget to free memory */
return (int)n;
}
示例使用/输出
$ ./bin/str_trim_realloc
t: 'prova'
内存使用/错误检查
$ valgrind ./bin/str_trim_realloc
==26078== Memcheck, a memory error detector
==26078== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26078== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==26078== Command: ./bin/str_trim_realloc
==26078==
t: 'prova'
==26078==
==26078== HEAP SUMMARY:
==26078== in use at exit: 0 bytes in 0 blocks
==26078== total heap usage: 2 allocs, 2 frees, 14 bytes allocated
==26078==
==26078== All heap blocks were freed -- no leaks are possible
==26078==
==26078== For counts of detected and suppressed errors, rerun with: -v
==26078== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
另一答案
有两种方法可以做到这一点:
- 第一:在其他变量中修剪原始变量,因此有两个变量:第一个变量有一个带空格的字符串,第二个字符串是第一个变量的内容,没有开始/结束空格。
- 第二:修改变量本身。
这样做的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
size_t trimInOtherVariable(char *out, size_t len, const char *str)
{
if(len == 0)
return 0;
const char *end;
size_t out_size;
// Trim leading space
while(isspace((unsigned char)*str)) str++;
if(*str == 0) // All spaces?
{
*out = 0;
return 1;
}
// Trim trailing space
end = str + strlen(str) - 1;
while(end > str && isspace((unsigned char)*end)) end--;
end++;
// Set output size to minimum of trimmed string length and buffer size minus 1
out_size = (end - str) < len-1 ? (end - str) : len-1;
// Copy trimmed string and add null terminator
memcpy(out, str, out_size);
out[out_size] = 0;
return out_size;
}
char *trimInSameVariable(char *str)
{
char *end;
// Trim leading space
while(isspace((unsigned char)*str)) str++;
if(*str == 0) // All spaces?
return str;
// Trim trailing space
end = str + strlen(str) - 1;
while(end > str && isspace((unsigned char)*end)) end--;
// Write new null terminator character
end[1] = ' ';
return str;
}
int main(void)
{
// Declare string for trimming
char buffer[] = " pr ova ";
size_t size;
// Declare pointers which will store trimmed variable
char *stringWithSpaces = (char *) malloc( sizeof(char)*(strlen(buffer)+1) );
char *stringWithoutSpaces = (char *) malloc( sizeof(char)*(strlen(buffer)+1) );
// Check if allocating memory is OK. Then copy string to trim inside pointer
if (stringWithSpaces == NULL || stringWithoutSpaces == NULL)
return -1;
else
strcpy(stringWithSpaces, buffer);
// Way 1: Trim 'stringWithSpaces' inside 'stringWithoutSpaces'
size = trimInOtherVariable(stringWithoutSpaces, strlen(buffer), stringWithSpaces);
// Way 2: Trim 'stringWithSpaces' inside itself
stringWithSpaces = trimInSameVariable(stringWithSpaces);
// Show trimmed strings
printf (
"String trimmed in other variable: "%s"
"
"String trimmed in same variable: "%s"
"
, stringWithoutSpaces, stringWithSpaces
);
// End function
return 0;
}
希望这对你有所帮助。
另一答案
您的程序至少包含以下错误:
#include
指令丢失了。你至少需要stdlib.h
和string.h
。main
被宣布返回int
,但是你从一个地方返回NULL
并从另一个地方返回t
(char*
类型)。- 它可能会或可能不会做它应该做的事情。它只删除开头和最后一个空格中的一个空格,而不是短语之前或之后的所有空格,并且以不必要的复杂方式进行。
这个程序似乎没有一种错误就是将数据写入任何结尾。
另一答案
你必须在程序结束前释放't'。也许您需要在代码中进行一些重构:
#include <stdlib.h> //realloc
#include <string.h> // memcpy
char *remove_space(char *s) {
char *t = 0;
if (s == 0) {
return 0;
} else {
int n = strlen(s);
t = malloc(sizeof(char) * n + 1);
for (int i = 0; i <= n; ++i) {
t[i] = s[i];
}
int k = 0;
if (s[0] == ' ') {
++k;
t = realloc(t, sizeof(char) * n);
for (int i = 0; i <= n - 1; ++i) {
t[i] = s[i + 1];
}
}
if (s[n - 1] == ' ') {
if (k == 1) {
int j = 0;
t = realloc(t, sizeof(char) * n - 1);
for (int i = 0; i <= n - 2; ++i) {
t[i] = t[i];
j = i;
}
t[j] = 0;
} else {
int j = 0;
t = realloc(t, sizeof(char) * n);
for (int i = 0; i <= n - 1; ++i) {
t[i] = t[i];
j = i;
}
t[j] = 0;
}
}
}
return t;
}
int main(void) {
char s[] = " prova ";
free(remove_space(s));
return 0;
}
检查valgrind:
valgrind --leak-check=full --show-reachable=yes ./program
==8753== Memcheck, a memory error detector
==8753== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8753== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==8753== Command: ./program
==8753==
==8753==
==8753== HEAP SUMMARY:
==8753== in use at exit: 0 bytes in 0 blocks
==8753== total heap usage: 3 allocs, 3 frees, 21 bytes allocated
==8753==
==8753== All heap blocks were freed -- no leaks are possible
==8753==
==8753== For counts of detected and suppressed errors, rerun with: -v
==8753== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
以上是关于C:错误分配指针[重复]的主要内容,如果未能解决你的问题,请参考以下文章