相关疑难解决方法(0)

访问数组越界没有错误,为什么?

我在C++程序中为这样的边界分配值:

#include <iostream>
using namespace std;
int main()
{
    int array[2];
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序打印34.应该是不可能的.我正在使用g ++ 4.3.3

这是编译和运行命令

$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4
Run Code Online (Sandbox Code Playgroud)

只有在分配时才array[3000]=3000会给我一个分段错误.

如果gcc没有检查数组边界,我怎么能确定我的程序是否正确,因为它可能会导致一些严重的问题?

我用上面的代码替换了

vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout …
Run Code Online (Sandbox Code Playgroud)

c++ arrays

157
推荐指数
6
解决办法
10万
查看次数

访问绑定的未定义行为之外的全局数组?

我今天刚上课了 - 阅读C代码和输入,如果程序实际运行,所需答案就是屏幕上显示的内容.其中一个问题被声明a[4][4]为一个全局变量,并且在该程序的一个点上,它试图访问a[27][27],所以我回答了类似" 访问一个超出其边界的数组是一个未定义的行为 ",但老师说它a[27][27]的值将为0.

之后,我尝试了一些代码来检查"所有未初始化的golbal变量是否设置为0"是否为真.好吧,这似乎是真的.

所以现在我的问题是:

  • 似乎已经清除了一些额外的内存并保留了代码运行.保留多少内存?为什么编译器会保留比应该更多的内存,它的用途是什么?
  • a[27][27]0所有环境?

编辑:

在该代码中,a[4][4]唯一声明的全局变量,并且还有一些更多本地变量main().

我在DevC++中再次尝试了该代码.所有这些都是0.但在VSE中并非如此,其中大多数值都是,0但有些值具有Vyktor指出的随机值.

c undefined-behavior

60
推荐指数
7
解决办法
3235
查看次数

是GCC的选择-O2打破这个小程序还是我有未定义的行为

我在一个非常大的应用程序中发现了这个问题,从中做了一个SSCCE.我不知道代码是否有未定义的行为或-O2打破它.

gcc a.c -o a.exe -O2 -Wall -Wextra -Werror它编译时打印5.

但是在编译时没有(例如)或取消注释2条注释行之一(防止内联)时打印25.-O2-O1

#include <stdio.h>
#include <stdlib.h>
// __attribute__((noinline)) 
int f(int* todos, int input) {
    int* cur = todos-1; // fixes the ++ at the beginning of the loop
    int result = input;
    while(1) {
        cur++;
        int ch = *cur;
        // printf("(%i)\n", ch);
        switch(ch) {
            case 0:;
                goto end;
            case 1:;
                result = result*result;
            break;
        }
    }
    end:
    return result;
}
int main() …
Run Code Online (Sandbox Code Playgroud)

c gcc inline-functions compiler-optimization

14
推荐指数
1
解决办法
610
查看次数

在C++中避免别名的"正确"方法是什么(例如在向自身添加容器元素时)?

std::vector<int> a;
a.push_back(1);
a.push_back(a[0]);
Run Code Online (Sandbox Code Playgroud)

刚刚了解到上面的代码非常危险.

(如果不明白为什么,你并不孤单......对我来说也不是很明显.)

我的问题:

  1. 处理它的"标准"方式是什么?制作一个新变量,然后立即将其分配给某些东西对我来说似乎有点奇怪.有没有更好的方法来处理它?

  2. 你如何训练自己注意这样的混叠问题?你在寻找什么样的模式?我不知道这种情况; 当我restrict在C中学习关键字时,我才学会了别名,现在才明白这个问题究竟是什么.


编辑:

我很乐意接受一个答案,但问题的第(2)部分似乎没有得到回答.我想知道人们使用什么策略来查找他们编写的代码中的别名错误.

到目前为止我提出的一个策略是避免在两个参数中传递相同的值.(在这种情况下,一个参数是隐式的,一个是显式的.)

是否还有其他容易注意到的事项需要注意和注意?

c++ lifetime pointer-aliasing

11
推荐指数
2
解决办法
312
查看次数

有一个指向保留向量元素的指针是否合法?

我很好奇这种事情是否合法:

std::vector<some_class_type> vec;
vec.reserve(10);
some_class_type* ptr = vec.data() + 3; // that object doesn't exist yet
Run Code Online (Sandbox Code Playgroud)

请注意,我没有尝试访问指向的值.

这是标准所说的data(),但我不确定它是否相关:

返回:指针,这[data(),data() + size())是一个有效的范围.对于非空向量,data() == &front().

c++ pointers vector undefined-behavior language-lawyer

10
推荐指数
1
解决办法
453
查看次数

可以使用std :: uintptr_t来避免越界指针算法的未定义行为吗?

现在我们知道,越界 - 指针算术具有未定义的行为,如本SO问题所述.

我的问题是:我们可以通过转换为std :: uintptr_t进行算术运算然后转换回指针来解决这种限制吗?是保证工作吗?

例如:

char a[5];
auto u = reinterpret_cast<std::uintptr_t>(a) - 1;
auto p = reinterpret_cast<char*>(u + 1); // OK?
Run Code Online (Sandbox Code Playgroud)

真实世界的用法是优化偏移内存访问 - 而不是p[n + offset]我想做的offset_p[n].

编辑使问题更明确:

给定一个pchar数组的基指针,如果p + n是一个有效的指针,将reinterpret_cast<char*>(reinterpret_cast<std::uintptr_t>(p) + n)保证产生相同的有效指针?

c++ pointers pointer-arithmetic

7
推荐指数
2
解决办法
1379
查看次数

过去数组对象的最后一个元素的基本原理是什么?

根据N1570(C11草案)6.5.6/8 添加剂操作员:

此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后,如果表达式Q指向一个超过数组对象的最后一个元素,则表达式(Q)-1指向最后一个元素数组对象

子条款6.5.6/9还包含:

此外,如果表达式P指向要么一个数组对象或一个过去的阵列对象的最后元件,并且表达的元件Q指向相同的数组对象的最后一个元素时,表达((Q)+1)-(P)具有相同的值((Q)-(P))+1和作为 -((P)-((Q)+1)),和如果表达式P指向一个超过数组对象的最后一个元素的值,则值为零,即使该表达式 (Q)+1未指向数组对象的元素.106)

这证明指针的算术是有效的:

#include <stdio.h>

int main(void)
{
    int a[3] = {0, 1, 2};
    int *P, *Q;

    P = a + 3; // one past the last element
    Q = a + 2; // last element

    printf("%td\n", ((Q)+1)-(P));
    printf("%td\n", ((Q)-(P))+1);
    printf("%td\n", -((P)-((Q)+1)));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望不允许指向数组越界的元素,其解除引用作为未定义的行为(数组溢出),因此它使它具有潜在的危险性.这有什么理由吗?

c c11

5
推荐指数
1
解决办法
595
查看次数

新的A [0] - 法律,但有什么用?它实际上做了什么?

根据C++ 03标准(5.3.4/7):

当direct-new-declarator中的表达式的值为零时,将调用分配函数以分配不带元素的数组.

通过我的阅读,这意味着此代码是合法的并具有指定的效果:

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
    A() : a_(++aa_) {};
    int a_;
    static int aa_;
};
int A::aa_ = 0;

int main()
{
    A* a = new A[0];
    // cout << "A" << a->a_ << endl; // <-- this would be undefined behavior
}
Run Code Online (Sandbox Code Playgroud)

当我在调试器下运行此代码时,我看到A永远不会调用构造函数. new不抛出,并返回一个非空的,显然有效的指针.但是,值为a->a_未初始化的内存.

问题:

  1. 在上面的代码中,a实际指向了什么?
  2. "分配没有元素的数组是什么意思?"
  3. 分配具有零元素的数组的实际用途是什么?

c++ new-operator

3
推荐指数
1
解决办法
265
查看次数

为什么"while(*sea ++ =*river ++);" 不能正常工作?

我的大学教授最近给了我们一个实现我们自己的智能指针类的任务.在他用于复制字符串的样板代码中,我发现这件作品很漂亮的语法糖:

while (*sea++ = *river++);// C Sting copy 
Run Code Online (Sandbox Code Playgroud)

我进一步研究了这段代码,发现它是strcpy.c中的确切代码,并在下面的stackoverflow问题中进一步解释它是如何工作的: "while(*s ++ =*t ++)"如何复制一个字符串?

当我尝试在我的下面的代码中使用这个语法糖时,它给出了垃圾作为结果并删除了存储在"river"中的字符串:

    #include<iostream>
    #include<cstring>

    using namespace std;
        void main()
        {
            const char *river = "water";// a 5 character string +  NULL terminator

            char *sea = new char[6];

            while (*sea++ = *river++);

            cout << "Sea contains: " << sea << endl;
            cout << "River contains: " << river << endl;
        }
Run Code Online (Sandbox Code Playgroud)

结果:
上述代码的结果

我知道我可以使用以下代码简单地实现所需的结果:

    int i = 0;
    while (i<6)
    {
        sea[i] = river[i];
        i++;
    }
Run Code Online (Sandbox Code Playgroud)

但这不是我想要的答案.我想知道我的while循环的实现或我的char指针的实例化有什么问题吗?

c++

3
推荐指数
2
解决办法
199
查看次数

指针运算与一个过去的数组元素然后解除引用,结果会是什么?

如果我取消引用一个数组并添加超过数组中可用元素的5,那么打印的值是多少?我在我的IDE中返回32767,这没有多大意义.

#include <stdio.h>

int main(void)
{

    int i;
    int meatBalls[5] = {1, 2, 3, 4, 5};

    printf("%12s %18s %6s\n", "Element", "Address", "Value");

    for(i=0; i < 5; i++) {
        printf("meatBalls[%d] \t %p \t %d \n", i, &meatBalls[i], meatBalls[i]);
    }

    printf("\nmeatBalls \t\t %p \n", meatBalls); /*already a pointer*/

    /*dereference meatBalls and it will update to the value e.g. 1*/

    printf("\n*meatBalls \t\t %d \n", *meatBalls); /*dereference with asterisk*/

    printf("\n*(meatBalls+2) \t\t %d \n", *(meatBalls+2)); /*dereference but also go through the array from 0 + …
Run Code Online (Sandbox Code Playgroud)

c arrays pointer-arithmetic clion

1
推荐指数
1
解决办法
354
查看次数

这个指针的内存地址是多少?

好的,所以在测试中我问了这个问题:

int* ptrA;    // assigned memory address 100
int a = 1;    // assigned memory address 600
ptrA = &a;

What is the memory address of ptrA + 2?
Run Code Online (Sandbox Code Playgroud)

我以为它是606(int是4个字节+其地址a是600 + 2 = 606但显然答案是608,我错过了什么才能使这个真实?

c++ memory int pointers

0
推荐指数
1
解决办法
304
查看次数