For completeness, here is a version that does not crash and looks like it does the right thing
#include <torch/script.h>
#include <torch/torch.h>
#include <iostream>

int main(int argc, char** argv) {
  std::cout << "NLL Example" << std::endl;

  constexpr int kBatchSize = 1;
  constexpr int kImageDim = 2;
  at::Tensor net_output = torch::log_softmax(
      torch::randn({kBatchSize, 2, kImageDim, kImageDim}), /*dim=*/1);
  std::cout << "Log softmax succeeded" << std::endl;

  at::Tensor ground_truth =
      torch::ones({kBatchSize, kImageDim, kImageDim}).to(at::kLong);
  std::cout << "Ground truth (ones) created" << std::endl;

  float actual_loss = 0;
  try {
    at::Tensor loss = torch::nll_loss2d(net_output, ground_truth);
    actual_loss = loss.item<float>();
  } catch (const std::exception& e) {
    std::cout << "Exception occured\n" << e.what() << std::endl;
    exit(-1);
  }

  std::cout << "Expected loss " << -net_output[0][1].mean().item<float>()
            << std::endl;
  std::cout << "Done with actual loss " << actual_loss << std::endl;
}


It outputs
NLL Example
Log softmax succeeded
Ground truth (ones) created
Expected loss 0.828792
Done with actual loss 0.828792