Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[VS2013] Step into code geeft ander resultaat dan run*

Pagina: 1
Acties:

  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33
Meer mensen met het probleem in VS2013 dat wanneer je stept de code anders werkt dan als je runt?

Voorbeeld: Ik debug een unit test en wanneer ik run (Continue) gaat het goed ,en als ik step (F10) krijg ik een NullReferenceException.
De immediate window zegt:

code:
1
Cannot obtain value of local or argument 'result' as it is not available at this instruction pointer, possibly because it has been optimized away.


8)7

[ Voor 3% gewijzigd door HMS op 05-11-2013 16:18 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

Om eerlijk te zijn lijkt me de mededeling redelijk duidelijk. Bedenk dat een debugger niet door je sourcecode heen loopt, maar door de daadwerkelijk gecompileerde code (en daar dan zo goed en zo kwaad als het kan de bijbehorende sourcecode bij zoekt). In dit geval is er blijkbaar een variabele die in je sourcecode nog wel 'bestaat', maar in de gecompileerde code duidelijk weg geoptimaliseerd is. Het is in dat geval voor de debugger ook niet meer mogelijk om de waarde van die variabele te achterhalen. Dat je code gewoon wel werkt komt natuurlijk omdat de opitmalisaties uiteraard slim genoeg zijn om je code niet onderuit te halen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
Ik doe vrij veel met unittests, en bij normale code (dus geen lamda) heb ik dit nog nooit meegemaakt.

Is het veel code waarin het optreed? (of is het zo weinig dat je het hier kan posten?)
Ik ben wel benieuwd :)

This message was sent on 100% recyclable electrons.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Bouw je wel in debug mode?

  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33
De source code is openbaar en onderdeel van een (pet project) EventStore implementatie bovenop MongoDB (staat hier: https://github.com/jvandertil/MongoES).

De snippit waar het mis gaat is vrij simpel (hele file hier):
C#:
1
2
3
4
5
6
7
                FindAndModifyResult result = _eventStreams.FindAndModify(documentQuery, SortBy.Null, update, true, document.IsNew);

                if (result.ModifiedDocument != null) // NullReferenceException (result == null)
                {
                    Logger.InfoFormat("Commit '{0}' successfully saved in stream {1}", commit.CommitId, streamId);
                    return;
                }


De if check gooit dus een NullReferenceException als je een step over doet van FindAndModify, maar werkt als je continue doet.

Het lijkt me erg vreemd dat de compiler die variable kan weg optimizen omdat ik hem daarna nog expliciet reference.

En ja, ik heb het project in Debug mode gebuild :)

edit: Hmm dit lijkt alleen op te treden als ik de ReSharper test runner gebruik. Bij de VS test runner werkt het wel naar behoren.

[ Voor 5% gewijzigd door HMS op 05-11-2013 21:53 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

In principe wordt result verder niet gebruikt in het executiepad. Alleen de ModifiedDocument property. Misschien heeft de compiler er wel een equivalent van gemaakt alla:

C#:
1
2
3
4
5
6
7
var modifiedDocument = _eventStreams.FindAndModify(documentQuery, SortBy.Null, update, true, document.IsNew).ModifiedDocument; 

if (modifiedDocument != null)
{ 
   Logger.InfoFormat("Commit '{0}' successfully saved in stream {1}", commit.CommitId, streamId); 
   return; 
}

[ Voor 9% gewijzigd door Janoz op 05-11-2013 21:59 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33
Dat zou kunnen, maar dat verklaart niet waarom ik dan een NullReferenceException krijg bij de if.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

Nou, in de geoptimaliseerde versie bestaat result helemaal niet. De waarde opvragen kan dan helemaal niet.

Ik wil trouwens nog wel even een dikke disclaimer toevoegen. Met c# heb ik helemaal geen ervaring. Ik laat 'gewoon' mijn algemene compiler kennis los op dit issue.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 12:59
Dat kan niet.
Run of Step mag geen verschil maken.

Het enige verschil tussen run en step is de tijd die tussen twee groepen instructies zit.

Het kan zijn dat er een interrupt of timeout is geweest, in een module die de debugger niet kan stoppen, waardoor een functie in een andere staat komt na een evaluatie als je stept, dan als je runt.

Probeer het ook eens met mindere optimizer, ja daar word je code groot en traag van. Moet je maar geen C# gebruiken.

Idem voor de disclaimer :P wel ervaring met dit soort problemen in ARM

[ Voor 14% gewijzigd door jeroen3 op 06-11-2013 00:16 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
offtopic:

Even op 't oog hoor en zonder diepgaande kennis van eventstores...
C#:
1
2
[DataMember]
public object Body { get; set; }
Kun je daar niet heel mooi generics voor gebruiken door een EventMessage<T> te maken?

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace MongoES
{
    [Serializable]
    [DataContract]
    public class EventMessage<T>
    {
        /// <summary>
        ///     Initializes a new instance of the EventMessage class.
        /// </summary>
        public EventMessage()
        {
            Headers = new Dictionary<string, T>();
        }

        /// <summary>
        ///     Gets the metadata which provides additional, unstructured information about this message.
        /// </summary>
        [DataMember]
        public Dictionary<string, T> Headers { get; set; }

        /// <summary>
        ///     Gets or sets the actual event message body.
        /// </summary>
        [DataMember]
        public T Body { get; set; }
    }
}


(Mogelijk i.c.m. een generic type constraint).

Of zeg ik dan iets heel doms?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

jeroen3 schreef op woensdag 06 november 2013 @ 00:14:
Dat kan niet.
Run of Step mag geen verschil maken.
Voor zover ik de vraag interpreteer maakt het ook geen verschil. Ik neem aan dat de nullreference optreed op het moment dat de debugger op pauze staat en de waarde van result opgevraagd wordt. De fout treed op tijdens het inspecteren, niet tijdens het draaien.
HMS schreef op dinsdag 05 november 2013 @ 21:50:
De if check gooit dus een NullReferenceException als je een step over doet van FindAndModify, maar werkt als je continue doet.
Hieruit maak ik op dat je de nullref krijgt, maar als je vervolgens op continue drukt de executie van het programma normaal verder gaat en goed afgerond wordt.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33
Janoz schreef op woensdag 06 november 2013 @ 09:50:
[...]

Voor zover ik de vraag interpreteer maakt het ook geen verschil. Ik neem aan dat de nullreference optreed op het moment dat de debugger op pauze staat en de waarde van result opgevraagd wordt. De fout treed op tijdens het inspecteren, niet tijdens het draaien.


[...]

Hieruit maak ik op dat je de nullref krijgt, maar als je vervolgens op continue drukt de executie van het programma normaal verder gaat en goed afgerond wordt.
Ah, dan heb ik het dus niet helemaal duidelijk uitgelegd. Dit is niet wat het probleem is.

Op het moment dat ik een step over doe op de eerste regel, dan krijg ik hoe dan ook (step of continue) een NRE bij de if check (tijdens het uitvoeren!). Doe ik op de eerste regel een Continue en break ik op de if check, dan werkt het gewoon en kan ik ook de waarde van result in de debugger ophalen.


@RobIII: Bedenk wel dat een event stream niet gelimiteerd is aan 1 soort event, wordt dan een beetje lastig om een return signature te maken ;). Daarnaast gaat er geen T in de Headers, maar een key-value van andere nuttige informatie. Object lijkt me daar de handigste keus.
Pagina: 1