【问题标题】:Why does a String declared as pointer to a character and was allocated a size of 2bytes, has its size being altered? [duplicate]为什么一个字符串被声明为一个字符的指针并且被分配了一个 2 字节的大小,它的大小被改变了? [复制]
【发布时间】:2015-01-03 18:32:22
【问题描述】:

我正在试验指针。我最初创建了一个指向字符的指针,并为该指针分配了 2 个字节的大小。然后我运行循环直到 1000 分配一些值。当我尝试打印字符串时,它会给我一整套已分配的值。

#include <iostream>
#include <string.h>

using namespace std;


int main()
{
    char *a = (char *)malloc(2);
    for (int i=0;i<10;i++)
       a[i]='a';
    cout<<a<<"\t"<<strlen(a)<<"\n";
    return 0;
}

输出如下

aaaaaaaaaa    10

我在 C 和 C++ 中运行相同的代码。他们给了我同样的结果。

首先想到的是,由于我使用了指针,所以 a[3] 的意思是 *(&a + 3): 这可以解释为什么我能够为该位置分配一个值。但是,即使我只为 String 分配了两个字节的内存,为什么我的字符串长度会发生变化?为什么编译器的行为方式不同?屏幕后面是什么?

操作系统:OS X 10.10.0 编译器:gcc ||克++ 架构:64 位架构

Edit1:这与段错误无关。

Edit2: 如果是因为 strlen 读取直到遇到空终止符。我没有在字符串的末尾声明它。

【问题讨论】:

  • 好吧,这与它为什么不崩溃无关!这是关于为什么要更改字符串的大小?
  • strlen 只计算连续字符(字节),直到遇到空终止符。它不知道 malloc 或您为任何东西分配的空间大小。因此,因为您在连续的内存区域中写入了 10 个“a”,strlen 将至少计为 10。malloc 分配的内存大小从未改变。你只是在做超出记忆范围的读写操作。
  • @TheUndeadFish 在 C 或 C++ 中,我们显式声明字符串的结尾。这将是矛盾的。
  • 我不明白你的意思。您分配了特定大小的内存,但随后写了过去。 C 和 C++ 不会阻止您做这些事情。实际上,一个程序的整个内存空间可以被认为是一个大数组。 C/C++ 在此之上强加了一组规则和想法,但是他们也希望您(程序员)遵循这些规则。当您违反这些规则时(例如通过写入超过分配内存的末尾),您可能会得到意想不到的结果。
  • @TheUndeadFish 感谢您回来。只是留给编译器的规则!我相信还有更多。我不能接受那个。谢谢你的朋友。

标签: c++ c string pointers memory-management


【解决方案1】:

此代码存在内存使用问题。只分配了 2 个字节的内存,但使用了 10 个字节。这将导致内存损坏。 那么行为是未定义的。

  for (int i=0;i<1 /*10*/;i++)

在您的情况下,最大 i 值可以是 1 而不是 10。剩下的 1 个再见是 \0 字符。

【讨论】:

  • 我试用时没有任何设置错误。当我使用 MAX 值在 INT_MAX 附近时会产生 Seg 错误(我只尝试过这个)。
  • @iMinion 谁说过段错误?当您开始使用未定义的行为时,无法保证您会因分段错误而得救。
  • @RedAlert 我同意你的看法。我明白行为是未定义的。我想知道背景是怎么回事。link。答案解释了内存损坏何时完成。认为行为未定义是矛盾的。
  • 如何定义内存损坏?您不知道您正在使用此代码修改谁的内存。后台发生的事情很简单,您正在写入未分配给a 的内存。其结果是未定义的。
  • @RedAlert 我的问题是为什么会这样?C++ 编译器是如何在后台工作的?即使我们知道它是未定义的,为什么结果会不同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多