更新:正在输出内存位置而不是所需的字符串

Posted

技术标签:

【中文标题】更新:正在输出内存位置而不是所需的字符串【英文标题】:Updated: Memory Location being outputted instead of desired string 【发布时间】:2017-01-22 04:04:22 【问题描述】:

->请在水平分隔线下方查看我编辑的问题:

我试图将一个字符串数组从一个函数返回到另一个函数。代码编译成功;但是,它在执行时失败了。我在下面包含了我的代码:

    string Occupant::LoadDataFunction()
    
        string array[5] = "hello", "you", "are", "a", "human";

        return array[5];
    

    void Occupant::LoadData()
    
        string loc_array[5];
        loc_array[5] = Occupant::LoadDataFunction();

        string park_array[5];
        park_array[5] = Occupant::LoadDataFunction();

        string lease_array[5];
        lease_array[5] = Occupant::LoadDataFunction();
    

我在调试代码的时候发现问题出在函数的return语句中:

    return array[5]

调试器有以下输出:

信号 = SIGSEGV(分段错误)

this = 乘员 * 常量 | 0x61ff2f 0x61ff2f

array = std::_cxx11::basic_string [5]

谁能告诉我我的 return 语句有什么问题,为什么会导致分段错误?谢谢

** 我知道网上还有很多其他类似的问题,但没有一个涉及return语句中的分段错误因此,如果这个问题没有被标记为重复,我将不胜感激。如果您需要更多信息,请在 cmets 框中告诉我。感谢您的帮助!


编辑谢谢大家,我没有注意到我刚刚修复的那个故障。我实际上是想返回整个数组,这次我用指针做到了。这是我的代码:

    string* Occupant::LoadDataFunction()
    
        string* array = new string[5];
        array[0] = "hello";
        array[1] = "hello";
        array[2] = "hello";
        array[3] = "hello";
        array[4] = "hello";

        return array;
    

    void Occupant::LoadData()
    
        string **loc_array = new string*[5];
        loc_array[5] = Occupant::LoadDataFunction();

        string **park_array = new string*[5];
        park_array[5] = Occupant::LoadDataFunction();

        string **lease_array = new string*[5];
        lease_array[5] = Occupant::LoadDataFunction();

        for (int i = 0; i < 5; i++)
        
            cout << &loc_array[i] << " : location" << endl;
            cout << &park_array[i] <<  " : parking" << endl;
            cout << &lease_array[i] <<  " : leased" << endl;
        
    

现在的问题是,当我运行代码时,不是总共打印 hello 十五次,而是打印内存地址。这是我得到的:

0xf56d50:位置

0xf56df8 : 停车

0xf56ea0 : 租用

0xf56d54:位置

0xf56dfc:停车

0xf56ea4:租用

0xf56d58:位置

0xf56e00 : 停车

0xf56ea8 : 租用

0xf56d5c:位置

0xf56e04 : 停车

0xf56eac : 租用

0xf56d60:位置

0xf56e08 : 停车

0xf56eb0 : 租用

我希望在输出内存地址的任何地方都会输出“Hello”字样。现在谁能解释一下?感谢您的所有回答!

【问题讨论】:

数组的索引从0开始,所以array[5]越界了。 您的返回类型是 string,但 arrayarraystring 是否使用std::Vector 选项? 关于您的笔记,您仍然可能遇到相同的问题并获得不同的行为。一个问题是使用arr[5] 来表示整个数组,而它实际上是一个越界元素,这是一个非常常见的问题。尽管其他人的行为与您的行为不同,但真正的答案是了解如何使用数组,这对您和他们都有帮助。但是,您也有其他问题,例如尝试返回数组,而这不能直接使用 C 数组完成。我建议使用std::array,因为它更“正常”。 你不能创建一个包含五个东西的数组,然后尝试访问第六个。 【参考方案1】:

要返回一个数组,请使用std::array,因为std::array 是可复制和可分配的,这与普通数组不同。

#include <array>
#include <algorithm>

typedef std::array<std::string, 5> Array5Strings;

Array5Strings LoadDataFunction()

    Array5Strings ret;
    std::fill(ret.begin(), ret.end(), "hello");
    return ret;

另外,我使用std::fill 快速将项目设置为“hello”。

Live Example


如果由于某种奇怪的原因您不能使用std::array,那么另一种选择是创建一个包含5 个字符串的数组的struct,并返回structstruct 是可复制的,因此可以直接从函数中返回。

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

struct Array5Strings

   std::string sArray[5];
;

Array5Strings LoadDataFunction()

    Array5Strings ret;
    std::fill(std::begin(ret.sArray), std::end(ret.sArray), "hello");
    return ret;


int main()

    Array5Strings val = LoadDataFunction();
    std::cout << val.sArray[0]; // prints the first value

Live Example

无论您选择哪个,请注意不涉及指针。

【讨论】:

第一选择很好用,@PaulMcKenzie,我只是不允许使用向量。与指针相比,这太容易了,我想知道为什么我的教授从来没有教过我这个:/ @NewbietoProgramming -- 实际上,struct 版本是std::array 的精简版。从本质上讲,struct 版本就是 std::array 实际所做的。不同之处在于std::array 有几个成员函数,operator [ ] 重载以访问项目等。【参考方案2】:

您正在使用越界索引访问数组。

当你有一个数组声明为:

    string loc_array[5];

有效的索引是0 - 4

使用

    loc_array[5] = Occupant::LoadDataFunction();

是未定义行为的原因。我怀疑你打算使用:

    loc_array[4] = Occupant::LoadDataFunction();

同样,你需要使用:

    park_array[4] = Occupant::LoadDataFunction();

    lease_array[4] = Occupant::LoadDataFunction();

您还需要更改Occupant::LoadDataFunction

string Occupant::LoadDataFunction()

    string array[5] = "hello", "you", "are", "a", "human";
    return array[4];

更新

Occupant::LoadDataFunction 的更新实现更好,但仍然存在问题。

    每次调用该函数时,都会分配一个 strings 数组。目前尚不清楚这是否是意图。如果这是本意,那么调用代码必须负责释放该内存。

    调用代码仍然受到超出我们边界内存访问的影响。线

    string **loc_array = new string*[5];
    

    5 string* 分配内存。 loc_array 的有效索引仍然是 0 - 4。因此,

    loc_array[5] = Occupant::LoadDataFunction();
    

    存在越界内存访问问题。不清楚您希望如何使用Occupant::LoadDataFunction 的返回值。因此,我无法提出解决问题的方法。

    线条

    park_array[5] = Occupant::LoadDataFunction();
    
    lease_array[5] = Occupant::LoadDataFunction();
    

    遇到同样的问题。

【讨论】:

我认为 OP 想一次返回所有数组成员 @M.M 这绝对是可能的。我会让 OP 澄清一下。 对不起,@RSahu,这就是我想要做的,但我已经解决了这个问题并最终遇到了一个新问题。请参阅上面的更新。 感谢@RSahu 指出这一点!我一直在犯这样的小错误而没有注意到它。无论如何谢谢:)【参考方案3】:

尝试返回array[4]。没有array[5],因为数组从索引 0 开始。

【讨论】:

欢迎来到 Stack Overflow!我推荐你take the tour。【参考方案4】:

大小为 N 的数组的范围是从 0 到 N-1。所以 5 不在范围内。并且你可能想要返回一个数组作为结果,但是数组是在函数LoadData中构造的,函数执行后,数组是无效的。您可以根据需要使用动态分配或使用全局变量。

当你使用动态分配数组时,你可以只使用string*而不是string**,你应该释放分配的内存。

【讨论】:

还有return语句? 我刚刚解决了这个问题,你是对的@cstur4,我实际上想返回整个数组。请在上面的问题中查看我的更新:)

以上是关于更新:正在输出内存位置而不是所需的字符串的主要内容,如果未能解决你的问题,请参考以下文章

加载默认 Xib 而不是所需的 Xib?

将连续的字符串数据拆分为所需的垂直输出

自动填充不会从所需的单元格开始,也不会填充

所需的依赖项未更新

指定的字符串不是电子邮件地址所需的格式。发送电子邮件时

Perl 正则表达式变量替换打印 1 而不是所需的提取