.NET debugger passes invalid value for method parameter of specific value types during expression evaluation
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
Let the value type `TestStruct` has 3 `byte` fields:
```C#
public record struct TestStruct(byte A, byte B, byte C)
{
public string Print(TestStruct other) => $"{this}/{other}";
public override string ToString() => $"{A}/{B}/{C}";
}
```
When you pass parameter to method `TestStruct.Print(TestStruct other)` while evaluating expressions using debugging features like Watch (Visual Studio), the debugger actually passes an invalid value to the method.
This bug depends on the layout of the value type;
Reproducible with:
- Value type with 5 `byte` fields
- Value type with 3 `short` fields
- Value type with 2 `short` fields and 1 enum field that have `short` as underlying type
- Value type with 1 `short` field and 3 `byte` fields
Not reproducible with:
- Value type with 4 `byte` fields
- Value type with 5 `short` fields
- Value type with 3 `int` fields
- Value type with 1 `int` field and 1 `byte` field
These bugs are reproducible on almost every debugging features, so I suspect this bug is from CLR debugging interface somewhere around `ICorDebugEval2`.
### Reproduction Steps
1. Create new C# Console Application
2. Paste the following code:
```C#
TestStruct v = default;
Console.WriteLine(v.Print(v));
public record struct TestStruct(byte A, byte B, byte C)
{
public string Print(TestStruct other) => $"{this}/{other}";
public override string ToString() => $"{A}/{B}/{C}";
}
```
3. Set breakpoint on line 2 (`Console.WriteLine(v.Print(v))`)
4. Run in Debug mode, Any CPU
5. Evaluate `v.Print(v)` using Watch (Visual Studio), Immediate Window (Visual Studio), or Debug Console (Visual Studio Code)
6. Confirm evaluation result is not `0/0/0/0/0/0`
### Expected behavior
Debugger should pass proper value.
`v.Print(v)` should return string `0/0/0/0/0/0`.
### Actual behavior
Debugger is not passing proper value.
`v.Print(v)` returns strings like `0/0/0/152/75/113`.
The return value varies between executions, but is consistent in a single breakpoint hit.
### Regression?
This issue is reproducible on almost every debugging features:
- Watch (Visual Studio)
- Immediate Window (Visual Studio)
- Debug Console (Visual Studio Code)
- Watch (dnSpy)
- Threads & Variables (Rider)
This issue is also reproducible on almost every .NET runtimes:
- .NET Framework 4.8
- .NET Core 6.0, 8.0, 9.0, 10.0
### Known Workarounds
1. Changing value type to reference type avoids the issue.
2. Changing layout of value type by adding extra fields to the value type may avoids the issue.
### Configuration
- Reproducible on almost every .NET runtime version
- OS: Windows 11 Pro 24H2, 26100.7462
- CPU: Intel(R) Core(TM) Ultra 7 265K
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.