首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >枚举上的Serde无标记属性会导致堆栈溢出。

枚举上的Serde无标记属性会导致堆栈溢出。
EN

Stack Overflow用户
提问于 2020-12-15 15:38:10
回答 2查看 2.5K关注 0票数 1

Im使用枚举上的untagged属性来序列化和反序列化JSON。

代码语言:javascript
复制
// Just an example of using `untagged` - not actual code with the issue.
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Message {
    String(String),
    X(X),
}

我在运行时为我的一些类型获得了一个fatal runtime error: stack overflow

通过使用Box,这些类型可能具有递归定义。

通常,在使用untagged属性时,什么会导致堆栈溢出?

文档没有说明任何限制,因此似乎它应该适用于任何编译的代码。

这是我在Mac上用仪器/采样器收集到的堆栈跟踪,__rust_probestack似乎是最后一个调用的函数,此时它大约有70个函数深。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-16 20:46:13

https://github.com/serde-rs/serde/issues/1062#issuecomment-335659227

通过将堆栈设置为16 to来修正:

export RUST_MIN_STACK=16777216 && cargo test

票数 0
EN

Stack Overflow用户

发布于 2020-12-16 13:40:56

根据您在注释中所说的内容,您有递归类型。问题来自于untagged的工作方式。下面是一个重现问题的最小示例:

代码语言:javascript
复制
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum Foo {
    Foo(Box<Foo>),
    Bar(String),
}

fn main() {
    let data = r#""Bar""#;

    let _v: Foo = serde_json::from_str(&data).unwrap();
}

游乐场

问题是,使用untagged时,Serde试图将数据解析为枚举的第一个变体,然后如果失败了,则返回并尝试第二个变体,依此类推。下面是上面这个例子的结果:

  1. Serde被要求解析一个类型为Foo的值,该值是无标记的,因此Serde试图解析一个与第一个变量匹配的值。
  2. 第一个变体是一个Box<Foo>,所以Serde试图解析一个Foo类型的值,该值是无标记的,所以Serde试图解析一个与第一个变量匹配的值。
  3. 第一个变体是一个Box<Foo>,所以Serde试图解析一个Foo类型的值,该值是无标记的,所以Serde试图解析一个与第一个变量匹配的值。
  4. 诸若此类。

注意,这与输入数据无关,这段代码甚至在尝试读取单个字节的数据之前都会失败!

为了避免这个问题,您必须确保Serde在递归之前总是使用一些数据,例如:

代码语言:javascript
复制
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum Foo {
    Foo(String, Box<Foo>),
    Bar(String),
}

fn main() {
    let data = r#""Bar""#;

    let _v: Foo = serde_json::from_str(&data).unwrap();
}

游乐场

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65309013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档