简体   繁体   English

寻找我在这里遇到访问冲突的原因

[英]Looking for insight into why I'm getting an access violation here

I'm trying to create a list of points whose z value will be modified by the alpha values of a grayscale image.我正在尝试创建一个点列表,其 z 值将被灰度图像的 alpha 值修改。 As the points are being assigned to a list, I keep getting an access violation.由于点被分配到一个列表,我不断收到访问冲突。 I noticed during debugging that the size of the alpha array is suddenly changing in the middle of the for loop, along with my width and height values.我在调试过程中注意到 alpha 数组的大小在 for 循环中间突然改变,以及我的宽度和高度值。 I'm new to C++ so I imagine it's an obvious mistake.我是 C++ 的新手,所以我想这是一个明显的错误。 Here's the relevant code:这是相关的代码:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

// image processing libs
#include "vendors/stb_image/stb_image.h"
#include "vendors/stb_image/stb_image_write.h"

#include "Image.h"
#include "Renderer.h"
#include "VertexBufferLayout.h"

// signed normalization function for scaling input value with a known input range to an output range
float snorm(float value, float in_Min, float in_Max) 
{
    float out_Value = ( ((1.0f - 1.0f) * ((value - in_Min) / (in_Max - in_Min))) + -1.0f );
    return out_Value;
}

int main(void) 
{   
    // CONSTANTS
    const int SCREEN_WIDTH = 2000;
    const int SCREEN_HEIGHT = 2000;
    // glsl version
    const char* glsl_version = "#version 330";

    Image image("res/images/drama_mask_white.jpg");
    // loads an image to greyscale (normal) and returns the path to that normal
    std::string normal_Path = image.ImgToGrayScale("gray_mask");
    image.GetAlphas(normal_Path);
    image.setMinMaxAlphas();
    
    const std::vector<float> * lcl_Alphas = &image.alpha_Map;
    const int lcl_Width = image.img_Width;
    const int lcl_Height = image.img_Height;

    const float x_Increment = 2.0f / lcl_Width; 
    const float y_Increment = 2.0f / lcl_Height;


    float positions[] = { 0 };
    //unsigned int indices[] = { 0 };
    unsigned int row = 0;
    unsigned int col = 0;
    unsigned int num_Rows = 0;
    unsigned int num_Cols = 0;
    unsigned int num_Verteces = 0; 
    unsigned int pos_Count = 0; 

    for (int i = 0; (unsigned)i < image.alpha_Map.size(); i++)  
    {
        // checks for the end of the row
        if (i > 0 && (i % (image.img_Width - 1)) == 0)
        {
            row++; // if we've reached the end of a row, increment row index
            num_Cols = col;
            col = 0; // reset column index at end of each row
        }


        // assign position values starting from bottom left
        // X
        positions[pos_Count] = -1.0f + (col * x_Increment);
        // Y
        positions[pos_Count + 1] = -1.0f + (row * y_Increment);
        // Z
        // ERROR OCCURS HERE
        positions[pos_Count + 2] = snorm(image.alpha_Map[i], image.min_Alpha, image.max_Alpha);
        pos_Count += 3;
        // indices
        //indices[i] = i;

        col++; // increment column index 
        num_Verteces++;
    }

    std::cout << "Num Verteces: " << num_Verteces << std::endl;
    std::cout << "Num Positions: " << pos_Count << std::endl;

    num_Rows = row; 

    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    // create window and context with core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    glfwSwapInterval(1);

    // checks if GLEW intializes correctly
    if (glewInit() != GLEW_OK)
        std::cout << "ERROR!" << std::endl;

    std::cout << glGetString(GL_VERSION) << std::endl;

    // enable blending
    GLCall(glEnable(GL_BLEND));
    // get source alpha, subtract from one to blend alpha at destination  
    GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));

    // init renderer object
    Renderer renderer;

    GLfloat test_Vertex[] = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.0f };

    while (!glfwWindowShouldClose(window)) {

        GLCall(glClearColor(0.0, 0.0, 0.0, 1.0));
        renderer.Clear();

        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, test_Vertex);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDrawArrays(GL_POINTS, 0, 1);

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for, and process events
        glfwPollEvents();
    }
    glfwTerminate();
 }

@Rabbid76 and @Peter had the right idea here... I needed to use std::vector because I was initializing the array with only element, but populating it during the for loop. @Rabbid76 和 @Peter 在这里有正确的想法......我需要使用 std::vector 因为我只用元素初始化数组,但在 for 循环期间填充它。 Once I converted to std::vector it worked fine.一旦我转换为 std::vector 它就可以正常工作。 Now to make this thing actually draw the points...现在要让这个东西真正画点......

I see you are a new contributor.我看到你是一个新的贡献者。 I think in the future you can do a better job at 'minimizing' your example code.我认为将来您可以在“最小化”示例代码方面做得更好。 The general idea: Try to delete lines to have the error happen with little code as possible, maybe you will find a line that makes the difference.总体思路:尝试删除行以使用尽可能少的代码发生错误,也许您会发现一行有所不同。 This also helps you find mistakes before you have to ask others.这也有助于您在询问他人之前发现错误。

I think a big problem here may be that your array of positions will always be of size 1. This makes it harder to figure out any other problems in the rest of the code till this is fixed.我认为这里的一个大问题可能是您的positions数组的大小始终为 1。这使得在修复此问题之前很难找出其余代码中的任何其他问题。

Using float positions[] = { 0 };使用float positions[] = { 0 }; means the compiler will only reserve enough space for the positions array to contain 1 float value.意味着编译器只会为位置数组保留足够的空间来包含 1 个浮点值。 So writing to positions[0] = 42 is valid, but writing to positions[1] = 42 can already be bad.因此写入positions[0] = 42是有效的,但写入positions[1] = 42可能已经很糟糕了。 Maybe you are lucky and your program crashes immediatly.也许您很幸运,您的程序会立即崩溃。 If you are unlucky your program will write to the memory past the end of your array, and if you are extra unlucky this memory contains something important.如果你不走运,你的程序将写入数组末尾的内存,如果你特别不走运,这个内存包含一些重要的东西。 It could contain something like the size of your vector of alphas or any other data in memory.它可能包含诸如 alpha 向量的大小或内存中的任何其他数据。 So the errors it causes can become very unpredictable.因此,它导致的错误可能变得非常不可预测。

    int main() {
      char greeting[] = "Hello World!\n";
      float positions[] = { 0 };
      positions[0] = 42; // GOOD inside array bounds
      positions[4] = 42; // BAD outside array bounds destroying other data
      std::cout << greeting;
    }

Here is an example where I break a hello-world greeting on purpose by writing out of bounds of an array. 这是一个示例,我通过写出数组的边界来故意破坏 hello-world 问候语。 If you provide information about the IDE or compiler you are using people are able to tell you how to enable or view warnings for such mistakes.如果您提供有关您使用的 IDE 或编译器的信息,人们能够告诉您如何启用或查看此类错误的警告。 For example GCC's -Wall or -Warray-bounds.例如GCC 的 -Wall或 -Warray-bounds。 Or you can Google it yourself by adding "out of bounds warning".或者您可以通过添加“越界警告”来自行搜索。

Output of the example示例的输出

    > clang++-7 -pthread -std=c++17 -o main main.cpp
    main.cpp:7:3: warning: array index 4 is past the end of the array
          (which contains 1 element) [-Warray-bounds]
      positions[4] = 42; // BAD outside array bounds destroying other data
      ^         ~
    main.cpp:5:3: note: array 'positions' declared here
      float positions[] = { 0 };
      ^
    1 warning generated.
    > ./main
    Hello Worl 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM